我一直在 SO 线程中寻找答案,但无法从之前的讨论中找出我的问题。我有一个 ListView ,它加载了大约 50 张图像(它曾经是大约 100 张,但这几乎没有加载任何图像)。通过适配器从 api 端点获取我的 JSON 内容(包括图像 URL)后,我的代码将其放入 ListView 中。
目前, picasso 有 50 张图片,当我向下滚动提要时,它会一次加载一张图片。我觉得好像将滚动条固定在 ListView 中的一个项目上会使该图像加载速度更快。但是,当我向上滚动时,它会将占位符放回原处并再次重新加载图像。有办法解决这个问题吗?
public class MainActivity extends Activity {
private List<Post> myPosts = new ArrayList<Post>();
protected String[] mBlogPostTitles;
public static final String TAG = MainActivity.class.getSimpleName();//prints name of class without package name
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(isNetworkAvailable()) {
GetBlogPostsTask getBlogPostsTask = new GetBlogPostsTask(); // new thread
getBlogPostsTask.execute();// don't call do in background directly
}else{
Toast.makeText(this, "Network is unavailable", Toast.LENGTH_LONG).show();
}
}
public boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if(networkInfo != null && networkInfo.isConnected()){
isAvailable = true;
}
return isAvailable;
}
private void populateListView() {
ArrayAdapter<Post> adapter = new MyListAdapter();
ListView list = (ListView) findViewById(R.id.postsListView);
list.setAdapter(adapter);
}
private class MyListAdapter extends ArrayAdapter<Post>{
public MyListAdapter() {
super(MainActivity.this, R.layout.item_view, myPosts);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// make sure we have a view to work with
View itemView = convertView;
if (itemView == null) {
itemView = getLayoutInflater().inflate(R.layout.item_view, parent,false);
}
//find the post to work with
Post currentPost = myPosts.get(position);
Context context = itemView.getContext();
String imageURL = currentPost.getImage();
if(imageURL == null || imageURL.isEmpty()){
ImageView imageView = (ImageView) itemView.findViewById(R.id.item_image);
imageView.setVisibility(View.GONE);
}else{
ImageView imageView = (ImageView) itemView.findViewById(R.id.item_image);
Picasso.with(context)
.load(imageURL)
.tag(context)
.placeholder(R.drawable.kanye8080s)
.error(R.drawable.stadiumarcadium)
.into(imageView);
imageView.setVisibility(View.VISIBLE);
}
//Username
TextView userText = (TextView) itemView.findViewById(R.id.item_txtUser);
userText.setText(currentPost.getUser());
//Time of post
TextView timeText = (TextView) itemView.findViewById(R.id.item_txtTime);
timeText.setText("" + currentPost.getTime());
//The actual post
TextView postText = (TextView) itemView.findViewById(R.id.item_txtPost);
postText.setText("" + currentPost.getPost());
//The actual post
TextView likesText = (TextView) itemView.findViewById(R.id.item_txtLikes);
likesText.setText("" + currentPost.getLikes());
return itemView;
}
}
private class GetBlogPostsTask extends AsyncTask<Object, Void, List> {
@Override
protected List doInBackground(Object[] params) {
int responseCode = -1;//need to have this variable outside scope of try/catch block
JSONObject jsonResponse = null;
StringBuilder builder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpget = new HttpGet(""); /// api endpoint redacted
try {
HttpResponse response = client.execute(httpget);
StatusLine statusLine = response.getStatusLine();
responseCode = statusLine.getStatusCode();
if(responseCode == HttpURLConnection.HTTP_OK){ //could have used just 200 value
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
while((line = reader.readLine()) != null){
builder.append(line);
}
jsonResponse = new JSONObject(builder.toString());
JSONArray jsonPosts = jsonResponse.getJSONArray("posts");
for(int i=0; i < jsonPosts.length(); i++ ){
JSONObject jsonPost = jsonPosts.getJSONObject(i);
int post_id = Integer.parseInt(jsonPost.getString("id"));
String post_user = jsonPost.getString("user");
String post_account = jsonPost.getString("account");
int post_time = Integer.parseInt(jsonPost.getString("time"));
String post_post = jsonPost.getString("post");
String post_image = jsonPost.getString("image");
int post_likes = Integer.parseInt(jsonPost.getString("likes"));
myPosts.add(new Post(post_id, post_user, post_account, post_time, post_post, post_image, "profile picture here", post_likes));
}
}else{
Log.i(TAG, "Unsuccessful HTTP Response Code: " + responseCode);
}
}
catch (MalformedURLException e){
Log.e(TAG, "Exception caught");
}
catch (IOException e){
Log.e(TAG, "Exception caught");
}
catch (Exception e){//must be in this order, this is the last, general catch
Log.e(TAG, "Exception caught", e);
}
return null;
}
@Override
protected void onPostExecute(List result) {
// call populateListView method here
populateListView();
super.onPostExecute(result);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
编辑:
我已将我的代码更新为一个 View 持有者模式,创建了两个单独的 View (一个用于带有图像的帖子,一个用于带有文本的帖子)并且还包括 picasso 的新 scroll detection capabilities .
我看到一些图像加载速度有所提高,至少当 View 在滚动时聚焦时,图像现在更有可能加载。但是,在向上滚动那些曾经加载过的相同图像时,它们会消失。感觉 Picasso 一次只加载 4-5 张图像并替换已加载的图像以腾出空间。我更新的代码如下:
public class MainActivity extends Activity {
private List<Post> myPosts = new ArrayList<Post>();
protected String[] mBlogPostTitles;
public static final String TAG = MainActivity.class.getSimpleName();//prints name of class without package name
...
private void populateListView() {
Activity activity = MainActivity.this;
ArrayAdapter<Post> adapter = new MyListAdapter();
ListView list = (ListView) findViewById(R.id.postsListView);
list.setAdapter(adapter);
list.setOnScrollListener(new SampleScrollListener(activity));
}
private class MyListAdapter extends ArrayAdapter<Post>{
public MyListAdapter() {
super(MainActivity.this, R.layout.item_view, myPosts);
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
String imageURL = myPosts.get(position).getImage();
if(imageURL == null || imageURL.isEmpty()){
return 1; // text based
}else{
return 0; // image based
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
PostViewHolder holder;
int type = getItemViewType(position);
View itemView = convertView;
// make sure we have a view to work with
if (itemView == null) {
holder = new PostViewHolder();
if(type == 1) {
itemView = getLayoutInflater().inflate(R.layout.item_view, parent, false);
} else {
itemView = getLayoutInflater().inflate(R.layout.image_post_view, parent, false);
holder.image = (ImageView) itemView.findViewById(R.id.item_image);
}
holder.user = (TextView) itemView.findViewById(R.id.item_txtUser);
holder.time = (TextView) itemView.findViewById(R.id.item_txtTime);
holder.post = (TextView) itemView.findViewById(R.id.item_txtPost);
holder.likes = (TextView) itemView.findViewById(R.id.item_txtLikes);
itemView.setTag(holder);
} else {
holder = (PostViewHolder) itemView.getTag();
}
//find the post to work with
Post currentPost = myPosts.get(position);
if(type != 1) {
Context context = itemView.getContext();
String imageURL = currentPost.getImage();
Picasso.with(context).setIndicatorsEnabled(true);
//Picasso.with(context).setLoggingEnabled(true);
Picasso.with(context)
.load(imageURL)
.tag(context)
.placeholder(R.drawable.kanye8080s)
//.skipMemoryCache()
.error(R.drawable.stadiumarcadium)
.fit()
.into(holder.image);
}
//Username
holder.user.setText(currentPost.getUser());
//Time of post
holder.time.setText("" + currentPost.getTime());
//The actual post
holder.post.setText(currentPost.getPost());
//Likes for the post
holder.likes.setText("" + currentPost.getLikes());
return itemView;
}
}
public class SampleScrollListener implements AbsListView.OnScrollListener {
private final Context context;
public SampleScrollListener(Context context) {
this.context = context;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
final Picasso picasso = Picasso.with(context);
if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_TOUCH_SCROLL) {
picasso.resumeTag(context);
} else {
picasso.pauseTag(context);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
// Do nothing.
}
}
...
}
问题出在哪里?我应该以某种方式在缓存中预加载这些图像吗?虽然我已经研究过 Picasso 的新优先级功能,但我是否应该告诉 Picasso 以某种方式按照它们在我的 ListView 中出现的顺序加载图像?有任何想法吗?如何在向上滚动时“保留”已加载的图像?
最佳答案
使用 picasso 调整大小
Picasso.with(context)
.load(imageURL)
.tag(context)
.placeholder(R.drawable.kanye8080s)
.error(R.drawable.stadiumarcadium)
.into(imageView)
.resize(x,y);
//这肯定有帮助
关于java - picasso 在 ListView 中向上滚动时不断重新加载图像,加载缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27771646/
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/