【问题标题】:Listview with Universal Image Loader带有通用图像加载器的列表视图
【发布时间】:2014-05-20 13:08:57
【问题描述】:

我在使用 Universal Image Loader 加载列表视图时遇到问题。问题是我不知道把函数放在哪里来调用它,因为总是出现 RuntimeException。例外是由于 doinBackground 中的 ImageLoader。

我的代码如下:

公共类 Listview 扩展 Activity 实现 View.OnClickListener {

private ListView lstView;
private ImageAdapter imageAdapter;

ArrayList<HashMap<String, Object>> MyArrList = new ArrayList<HashMap<String, Object>>();

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    // ProgressBar
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

    setContentView(R.layout.activity_list);

    // ListView and imageAdapter
    lstView = (ListView) findViewById(R.id.listView1);
    lstView.setClipToPadding(false);
    imageAdapter = new ImageAdapter(getApplicationContext());
    imageAdapter.notifyDataSetChanged();//When add new photos, refresh the view
    lstView.setAdapter(imageAdapter);

    lstView.invalidateViews();

    setProgressBarIndeterminateVisibility(true);
    new LoadContentFromServer().execute();

}


class LoadContentFromServer extends AsyncTask<Object, Integer, Object> {

    @Override
    protected Object doInBackground(Object... params) {

        String url = "http://xxxxxxxxxxxxxx/xxxxxxx/Xxxx.php";
        String photo_id_new;
        String photo_id_prev = "";
        JSONArray data;
        imageAdapter.notifyDataSetChanged();

        try {
            data = new JSONArray(getJSONUrl(url));

            MyArrList = new ArrayList<HashMap<String, Object>>();
            HashMap<String, Object> map;

            for(int i = 0; i < data.length(); i++) {

                JSONObject c = data.getJSONObject(i);
                map = new HashMap<String, Object>();

                photo_id_new = c.getString("photo_id");

                map.put("ImageID", c.getString("photo_id"));

                map.put("NameAcc", c.getString("nameacc"));
                map.put("PriceAcc", c.getString("price"));
                map.put("BrandAcc", c.getString("brand"));
                map.put("Shopname", c.getString("shopname"));
                map.put("Shopcity", c.getString("city"));
                map.put("Shopcountry", c.getString("country"));

                map.put("UserName", c.getString("forename"));
                map.put("UserSurname", c.getString("surname"));

                //If the new photo it's different to the previous, doesn't show and create more rows
                if(!photo_id_prev.equals(photo_id_new)){
                    // Thumbnail Get ImageBitmap To Object
                    //Bitmap newBitmap = loadBitmap(c.getString("hyperlink"));
                    Bitmap newBitmap2 = ImageLoader.getInstance().loadImageSync(c.getString("hyperlink"));
                    Log.i("INFO", "Hyperlink:  " + c.getString("hyperlink"));

                    map.put("ImageThumBitmap", newBitmap2);
                    map.put("Repeat", "1"); //To know if it is a new photo

                } else {
                    // no new photo
                    map.put("Repeat", "0");
                    Log.i("INFO", "Inside else");

                }

                photo_id_prev = photo_id_new;
                Log.i("INFO", "Previous photo id:  "+photo_id_prev);

                MyArrList.add(map);

                publishProgress(i);

            }

        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalStateException e){
            e.printStackTrace();

        }

        return null;
    }

    @Override
    public void onProgressUpdate(Integer... progress) {
        imageAdapter.notifyDataSetChanged();
    }

    @Override
    protected void onPostExecute(Object result) {
        setProgressBarIndeterminateVisibility(false); // When Finish
    }
}

public class ImageAdapter extends BaseAdapter {

    private Context mContext;

    public ImageAdapter(Context context) {
        mContext = context;
    }

    public int getCount() {
        return MyArrList.size();
    }


    public Object getItem(int position) {
        return MyArrList.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        //View row = convertView;
        ViewHolder holder;

        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .resetViewBeforeLoading(true)
                .cacheInMemory(true)
                .cacheOnDisc(true)
                .bitmapConfig(Bitmap.Config.RGB_565) // default
                .displayer(new SimpleBitmapDisplayer())
                .imageScaleType(ImageScaleType.EXACTLY)
                .build();

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
                .threadPriority(Thread.MAX_PRIORITY).threadPoolSize(5)
                .denyCacheImageMultipleSizesInMemory()
                .memoryCache(new UsingFreqLimitedMemoryCache(6 * 1024 * 1024))
                .discCacheFileNameGenerator(new Md5FileNameGenerator())
                .tasksProcessingOrder(QueueProcessingType.LIFO)
                .build();

        ImageLoader.getInstance().init(config);

        Object repeat = MyArrList.get(position).get("Repeat");

        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int height = metrics.heightPixels;
        int width = metrics.widthPixels;

        //Try when row = null
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            convertView = inflater.inflate(R.layout.activity_column, null);

            holder = new ViewHolder();

            holder.imageView = (ImageView) convertView.findViewById(R.id.ColImgPath);

            holder.tvUsername = (TextView) convertView.findViewById(R.id.tVforename);
            holder.tvUserSurname = (TextView) convertView.findViewById(R.id.tVsurname);
            holder.ivProfilePhoto = (ImageView) convertView.findViewById(R.id.pphoto);

            holder.tvNameAcc = (TextView) convertView.findViewById(R.id.N);
            holder.tvBrandAcc = (TextView) convertView.findViewById(R.id.B);
            holder.tvPriceAcc = (TextView) convertView.findViewById(R.id.P);
            holder.tvShopAcc = (TextView) convertView.findViewById(R.id.S);

            convertView.setTag(holder);
        }
        else{
            holder = (ViewHolder) convertView.getTag();
        }

        String url = (MyArrList.get(position).get("ImageThumBitmap").toString());

        // ColImage
        holder.imageView.setPadding(5, 5, 5, 5);
        //holder.imageView.setScaleType(ImageView.ScaleType.CENTER);
        holder.imageView.setRotation(90);

        //Depends on the photo show or hidden the name and surname
        if(repeat.equals("1")){

            holder.imageView.setVisibility(View.VISIBLE);
            holder.tvUserSurname.setVisibility(View.VISIBLE);
            holder.tvUsername.setVisibility(View.VISIBLE);
            holder.tvUserSurname.setText(MyArrList.get(position).get("UserSurname").toString());
            holder.tvUsername.setText(MyArrList.get(position).get("UserName").toString());

            try {
                //Bitmap bmp = ((Bitmap) MyArrList.get(position).get("ImageThumBitmap"));

                //int size = Math.min(bmp.getWidth(), bmp.getHeight());
                //int x = (bmp.getWidth() - size) / 16;
                //int y = (bmp.getHeight() - size) / 9;
                //Bitmap result = bmp.createBitmap(bmp, x, y, size, size);

                //Bitmap photobitmap1 = Bitmap.createScaledBitmap(bmp, width/2, height/2, true);
                //holder.imageView.setImageBitmap(bmp);

                ImageLoader.getInstance().displayImage(url, holder.imageView);

                //holder.imageView.setImageBitmap((Bitmap) MyArrList.get(position).get("ImageThumBitmap"));

            } catch (Exception e) {
                // When Error
                holder.imageView.setImageResource(android.R.drawable.ic_menu_report_image);
            }

        }
        else {
            //If the photo_id is repeated these params are not shown
            holder.tvUserSurname.setVisibility(View.GONE);
            holder.tvUsername.setVisibility(View.GONE);
            holder.imageView.setVisibility(View.GONE);

        }

        // ColNameAcc
        holder.tvNameAcc.setPadding(20, 0, 0, 0);
        holder.tvNameAcc.setText(MyArrList.get(position).get("NameAcc").toString());

        // ColBrandAcc
        holder.tvBrandAcc.setPadding(20, 0, 0, 0);
        holder.tvBrandAcc.setText(MyArrList.get(position).get("BrandAcc").toString());

        // ColPriceAcc
        holder.tvPriceAcc.setPadding(20, 0, 0, 0);
        holder.tvPriceAcc.setText(MyArrList.get(position).get("PriceAcc").toString() 

        // ColShopAcc
        holder.tvShopAcc.setPadding(20, 0, 0, 0);
        holder.tvShopAcc.setText(MyArrList.get(position).get("Shopname").toString());

        return convertView;

    }

}

public static class ViewHolder {
    ImageView imageView;
    TextView tvUsername;
    TextView tvUserSurname;
    ImageView ivProfilePhoto;

    TextView tvNameAcc;
    TextView tvBrandAcc;
    TextView tvPriceAcc;
    TextView tvShopAcc;
}

}

Logcat 错误:

05-20 13:52:50.496    6524-3500/com.AndroidUK.SocialApp.app E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #4
Process: com.AndroidUK.SocialApp.app, PID: 6524
java.lang.RuntimeException: An error occured while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:300)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
        at java.util.concurrent.FutureTask.run(FutureTask.java:242)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:841)
 Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6094)
        at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:824)
        at android.view.View.requestLayout(View.java:16455)
        at android.view.View.requestLayout(View.java:16455)
        at android.view.View.requestLayout(View.java:16455)
        at android.view.View.requestLayout(View.java:16455)
        at android.view.View.requestLayout(View.java:16455)
        at android.view.View.requestLayout(View.java:16455)
        at android.widget.AbsListView.requestLayout(AbsListView.java:1916)
        at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:814)
        at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:6280)
        at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
        at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
        at com.AndroidUK.SocialApp.app.Listview$LoadContentFromServer.doInBackground(Listview.java:212)
        at android.os.AsyncTask$2.call(AsyncTask.java:288)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)

           在 android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 在 java.lang.Thread.run(Thread.java:841)

我也有刷新列表视图的问题,因为数据来自数据库,我不知道如何通知有新照片。有时应用程序会关闭,因为我上传了一张新照片。当我上传照片并且没有关闭我查看列表视图的应用程序时会发生这种情况。

谢谢

【问题讨论】:

  • 添加日志会有所帮助..

标签: android android-listview android-asynctask android-image universal-image-loader


【解决方案1】:

您正在从非主线程调用 imageAdapter.notifyDataSetChanged() ..例如在 onPostExecute() 中调用。 onPostExecute() 是执行 UI 操作、更新等的方法。doInBackground(),顾名思义,它只做后台操作,比如从文件、网络等

【讨论】:

  • 小注,或“建议”:如果您刚刚开始使用 Universal Image Loader...我建议您评估使用 Picasso (square.github.io/picasso) 的可能性,它可以工作更好、更灵活、维护更好。
  • 我会尝试这两件事,更改 notifyDataSetChanged 并实现 Picasso。我听过毕加索,但我认为它更容易通用,但不起作用,因此我尝试使用其他库....
  • 要使用毕加索我必须在 doInbackground 中放入的内容来将 url 转换为位图?
  • 好吧,我不会把位图放到那里的地图中,也许你的地图的其他条目没问题,但是对于位图,我会“按需”加载它们并让毕加索处理它。比如:Picasso.with(context).load("i.imgur.com/DvpvklR.png").into(imageView); 你在 UI Thread 上调用 picasso,它会为你做后台工作。
猜你喜欢
  • 1970-01-01
  • 2014-10-31
  • 2016-07-07
  • 1970-01-01
  • 2014-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多