簡體   English   中英

使用畢加索完成圖像加載時,Android RecyclerView凍結

[英]Android RecyclerView freezes when image loading is done using Picasso

在我的Android應用中,主頁上有一個recycleerview,其中每個項目都包含cardviews。 首先,我調用ParseServer以獲取服務器上的數據並將其傳遞給recyclerview適配器。 我將圖像URL以及其他詳細信息傳遞給適配器類。 在我的MainActivity.java中

Parse.initialize(this, "key1", "key2");
        ParsePush.subscribeInBackground("", new SaveCallback() {

            @Override
            public void done(ParseException e) {
                if (e == null) {
                      Log.d("com.parse.push", "successfully subscribed to the broadcast channel.");
                    } else {
                      Log.e("com.parse.push", "failed to subscribe for push", e);
                    }
            }
        });
        if(haveNetworkConnection()){
                new task().execute();

mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
        mRecyclerView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);

從服務器獲取數據的類任務:

public class task extends AsyncTask<Void, Void, Void>{


        ProgressDialog mProgressDialog;
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            rel.setVisibility(View.VISIBLE);
            pro.setVisibility(View.VISIBLE);
            titles.clear();
            images.clear();
            venues.clear();
            timings.clear();
            urgent.clear();
        }
        @Override
        protected Void doInBackground(Void... params) {
            ParseQuery<ParseObject> query = ParseQuery.getQuery("notices");
                try {
                    List<ParseObject> ob = query.find();
                    for(ParseObject obj:ob){
                        String str = obj.getString("title");
                        String str1 = obj.getString("venue");
                        String str2 = obj.getString("timing");
                        ParseFile file = obj.getParseFile("images");
                        String str3 = obj.getString("urgent");
                        String url;
                        if(file!=null)
                            url = file.getUrl();
                        else{
                            url = "https://www.medidirect.com.au/MEDIstores/_images/no-thumb.png";
                        }
                        titles.add(str);
                        images.add(url);
                        venues.add(str1);
                        timings.add(str2);
                        urgent.add(str3);
                    }
                } catch (ParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }


            return null;
        }
        @Override
        protected void onPostExecute(Void result) {
            AdapNotice mAdapter = new AdapNotice(MainActivity.this,titles,images,venues,timings,urgent);
            if(titles.size()<1)
                Toast.makeText(MainActivity.this, "Oops, Something went wrong. Please try again", 300).show();
            mRecyclerView.setAdapter(mAdapter);
            pro.setVisibility(View.GONE);
            rel.setVisibility(View.GONE);
        }
    }

在AdapNotice類中,這是recyclerview適配器:

public class AdapNotice extends RecyclerView.Adapter<AdapNotice.ViewHolder>{


     Activity activity;
     ArrayList<String> _titles = new ArrayList<String>();
     ArrayList<String> _images = new ArrayList<String>();
     ArrayList<String> _venues = new ArrayList<String>();
    ArrayList<String> _timings = new ArrayList<String>();
    ArrayList<String> _urgents = new ArrayList<String>();
    private int lastPosition = -1;
    int pos;
     public AdapNotice(Activity a, ArrayList<String> titles, ArrayList<String> images, ArrayList<String> venues, ArrayList<String> timings, ArrayList<String> urgent) {
         activity = a;
         _titles = titles;
         _images = images;
         _venues = venues;
         _timings = timings;
         _urgents = urgent;
     }
     public static class ViewHolder extends RecyclerView.ViewHolder{
        // each data item is just a string in this case
        public TextView title;
         public ImageView imgview,urgent;
         public TextView venue,venuetext,abctext;
         public TextView timing,timingtext,abc1text;
        public ViewHolder(View v) {
            super(v);
            title = (TextView) v.findViewById(R.id.title);
            imgview = (ImageView) v.findViewById(R.id.img_notice);
            venue = (TextView) v.findViewById(R.id.venue);
            timing = (TextView) v.findViewById(R.id.timing);
            venuetext = (TextView)v.findViewById(R.id.venuetext);
            abctext = (TextView)v.findViewById(R.id.abctext);
            timingtext = (TextView)v.findViewById(R.id.timingtext);
            abc1text = (TextView)v.findViewById(R.id.abc1text);
            urgent = (ImageView)v.findViewById(R.id.urgentstar);
        }

    }
    @Override
    public int getItemCount() {
        // TODO Auto-generated method stub
        if(_titles.size()<=0)
            return 0;
        return _titles.size();
    }
    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        // TODO Auto-generated method stub
        try{
            holder.title.setText(_titles.get(position));
            if(_urgents.get(position).contains("yes")){
                holder.urgent.setVisibility(View.VISIBLE);
            }
            pos = position;
            if(!_venues.get(position).contentEquals("---")){
                holder.venuetext.setVisibility(View.VISIBLE);
                holder.venue.setVisibility(View.VISIBLE);
                holder.abctext.setVisibility(View.VISIBLE);
                holder.venue.setText(_venues.get(position));
            }
            if(!_timings.get(position).contentEquals("---")){
                holder.timingtext.setVisibility(View.VISIBLE);
                holder.timing.setVisibility(View.VISIBLE);
                holder.abc1text.setVisibility(View.VISIBLE);
                holder.timing.setText(_timings.get(position));
            }
            Target target = new Target() {

                @Override
                public void onPrepareLoad(Drawable arg0) {
                    // TODO Auto-generated method stub
                    Animation anim = AnimationUtils.loadAnimation(activity, R.anim.rotate);
                    holder.imgview.setImageResource(R.drawable.loading);
                    holder.imgview.startAnimation(anim);

                }

                @Override
                public void onBitmapLoaded(Bitmap arg0, LoadedFrom arg1) {
                    // TODO Auto-generated method stub
                    holder.imgview.clearAnimation();
                    holder.imgview.setImageBitmap(arg0);
                    Log.i("completed", pos+" completed");
                    storeDB obj = new storeDB(_titles.get(pos), _venues.get(pos), _timings.get(pos), DbBitmapUtility.getBytes(arg0), _urgents.get(pos));
                    obj.execute();
                }

                @Override
                public void onBitmapFailed(Drawable arg0) {
                    // TODO Auto-generated method stub
                    holder.imgview.clearAnimation();
                    holder.imgview.setImageResource(R.drawable.error);

                }
            };
            Picasso.with(activity).load(_images.get(position)).into(target);
        }catch(Exception e){
            e.printStackTrace();
        }



    }
    private class storeDB extends AsyncTask<Void, Void, Void>{

        String title,venue,timing,urgent;
        byte[] image;
        public storeDB(String one, String two, String three, byte[] four, String five){
            title = one;
            venue = two;
            timing = three;
            image = four;
            urgent = five;
        }
        @Override
        protected Void doInBackground(Void... params) {
            SQLiteHandler handler = new SQLiteHandler(activity);
            handler.addNotice(title, venue, timing, image, urgent);
            handler.close();
            return null;
        }

    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {
            View v = LayoutInflater.from(parent.getContext()).inflate(
                    R.layout.item, parent, false);
            Animation animation = AnimationUtils.loadAnimation(activity, (arg1>lastPosition)?R.anim.up_from_bottom:R.anim.down_from_top);
            v.startAnimation(animation);
            ViewHolder vh = new ViewHolder(v);
            return vh;

    }
}

我將圖片網址傳遞到畢加索庫,該庫將圖片加載到目標中。 直到畢加索未提取圖像為止,我正在顯示另一個加載圖像並為其提供旋轉動畫效果。

有時候,即使圖像是由畢加索加載的,它也不會在imageview中顯示。 旋轉動畫停止並且加載的圖像也未顯示在imageview中。 此外,加載imageview時,主視圖有時會凍結。

因此,我該如何解決此問題並使我的應用程序運行更流暢?

提前致謝。

加載動畫停止

更新我發現凍結問題是由於對目標的引用不足。 我以很強的參考力解決了它,但是我該如何解決掛起的問題呢? 當我滾動時,App被掛起了一段時間。

您可以使用一種簡單的方法

Picasso.with(context)
.load(url)
.placeholder(R.drawable.user_placeholder)
.error(R.drawable.user_placeholder_error)
.into(imageView);

在加載圖像之前將顯示placholder圖像,如果發生錯誤,則將顯示錯誤圖像

UPDATE存儲在數據庫中只需編寫這么多樣板代碼

class MyTarget implements Target {

private ImageView imageView;

 public MyTarget(ImageView imageView) {
     this.imageView = imageView;
 }

@Override
 public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
     this.imageView.setImageBitmap(bitmap);
     //store your bitmap as you were storing 
 }

}

接着

Picasso.with(context)
.load(url)
.placeholder(R.drawable.user_placeholder)
.error(R.drawable.user_placeholder_error)
.into(new MyTarget(imageView));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM