毕加索不断重装的图像,同时在列表视图中向上滚动,慢慢负荷 [英] Picasso keeps reloading images while scrolling upwards in listview, loads slowly

查看:220
本文介绍了毕加索不断重装的图像,同时在列表视图中向上滚动,慢慢负荷的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找的SO线程的答案,但无法从previous讨论,找出我的问题。我有一个列表视图,它加载约50幅图像(它使用的是100,但这几乎没有加载任何图像的话)。从API端点抓住我的JSON内容(包括图片的URL),通过适配器后,我的code把它放到列表视图中。

I have been searching SO threads for answers but couldn't figure out my issue from previous discussion. I have a listview which loads about 50 images (it used to be about 100 but this was barely loading any images at all). After grabbing my JSON content (including image URL) from an api endpoint, through an adapter, my code puts it inside the listview.

目前,有50张图片,毕加索将加载一个图像,我向下滚动,在进料的时候。我觉得,如果保持滚动的列表视图固定在一个项目将使该图像加载速度更快。当我向上滚动,但是,它会将占位符回,并再次重新加载图像。有没有办法来解决这个问题呢?

Currently, with 50 images, picasso will load one image at a time as I scroll down on the feed. I feel as if keeping the scroll fixed on one item in the listview will make that image load faster. As I scroll up, however, it puts the placeholder back in and reloads the image again. Is there a way to solve this issue?

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);
    }
} 

任何帮助将大大AP preciated,

any help would be greatly appreciated,

感谢你!

编辑:

大家好,

我已经更新了我的code到视图座模式,创建了两个单独的视图(一个用于图像,一个是只有文字后后),还包括毕加索的新的滚动检测能力的。

I have updated my code into a view holder pattern, created two separate views (one for a post with an image, one for a post with just text) and also included Picasso's new scroll detection capabilities.

我已经看到在一些加载更快的图像的一种改进,至少当视点被聚焦的同时滚动,图像更可能现在来加载。然而,在滚动了这些曾经被加载相同的图像,消失。感觉好像毕加索只装载4-5张图像,并更换已经加载,以腾出空间的人。我的更新code是如下:

I have seen an improvement in some of the images loading quicker, at least when the view is focused while scrolling, the image is more likely to load now. However, on scroll up those same images that were once loaded, disappear. It feels as if Picasso is only loading 4-5 images at a time and replacing the ones already loaded to make room. My updated code is below:

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.
        }
    }


    ...
}

在哪里的问题从何而来呢?我应该是$ P $在高速缓存中以某种方式ploading这些图片?虽然我已经研究过毕加索的新的优先级功能,我应该告诉毕加索以某种方式在它们出现在我的列表视图的顺序加载图像?有任何想法吗?我怎样才能保持那些已经被装上向上滚动的图像?谢谢!

Where is the issue coming from? Should I be preloading these images somehow in the cache? While I have already looked into Picasso's new priority feature, should I be telling Picasso somehow to load images in the order in which they appear in my listview? Any ideas? How can I "keep" images that have already been loaded on scroll up? Thanks!

- 全天候

推荐答案

我想看看两件事情。

第一是图像加载的尺寸。我不知道默认最大缓存大小是毕加索的东西,但它听起来像是你可能只需几个图像超出,会引起别人从缓存中清除。

Number one is the sizes of the images being loaded. I don't know what the default maximum cache size is in Picasso, but it sounds like you may be exceeding it with just a few images, causing the others to be evicted from the cache.

排名第二的可能不是核心问题,也有利于性能。 你是做了很多findViewById()调用,这是相当昂贵的。 看看进入ViewHolder模式的缓存的查询。

Number two is probably not the core issue, but also contributes to performance. You are doing a lot findViewById() calls, which are fairly expensive. Look into the "ViewHolder" pattern for "caching" those lookups.

编辑 - 看<一href="http://stackoverflow.com/questions/23280242/using-picasso-with-custom-disk-cache#answer-23281195">Jake沃顿商学院的回答类似的问题获得更详细的

Edit - see Jake Wharton's answer to a similar question for more detail

这篇关于毕加索不断重装的图像,同时在列表视图中向上滚动,慢慢负荷的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆