使用asynctask和适配器显示远程图像android

时间:2012-01-19 10:54:27

标签: android android-arrayadapter android-asynctask

我刚刚开始研究android,似乎我遇到了一些多线程问题。有人可以看看下面的代码并告诉我这里我做错了什么。

public class TestHttpActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    URL theurl=null;
    try {
        theurl = new URL("http://myurlpath/androidimages");
    } catch (MalformedURLException e) {

        Log.w("alice","malformed");
    }
    GridView gallery=(GridView)findViewById(R.id.wowgridview);
    String[] imagesarray=new String[]{"1.jpg","2.jpg","3.jpg"};
    TheAsyncAdapterNew imgAdapter=new TheAsyncAdapterNew(this, imagesarray,theurl);
    gallery.setAdapter(imgAdapter);

}}

asyncadapter如下: -

public class TheAsyncAdapterNew extends ArrayAdapter<String> {
private Activity mycontext;
private String[] myimagesarray;
private URL myurl;
private Hashtable<Integer,ImageView> thegreatviewholders;
public TheAsyncAdapterNew(Activity context,String[] imagesarray,URL theurl) {
    super(context, R.layout.theadapterlayout,imagesarray);
    mycontext=context;
    myimagesarray=imagesarray;
    myurl=theurl;
    thegreatviewholders=new Hashtable<Integer,ImageView>();
}
@Override
public View getView(int position,View convertview,ViewGroup theparent){

    View myview=convertview;
    String mylocalurlstring=myimagesarray[position];
    MyviewHolder theholder;
    if(myview==null){
        LayoutInflater inflater=mycontext.getLayoutInflater();
        myview=inflater.inflate(R.layout.theadapterlayout, null,true);
        ImageView mylocalimageview=(ImageView) myview.findViewById(R.id.icon);
        theholder=new MyviewHolder();
        theholder.theimageview=mylocalimageview;
        myview.setTag(theholder);
    }else{
        theholder=(MyviewHolder)myview.getTag();

    }
    thegreatviewholders.put(position,theholder.theimageview);
    Bundle thebundle=new Bundle();
    thebundle.putString("thelocalurl",mylocalurlstring);
    thebundle.putInt("theposition",position);
    new Thethreadasynctask().execute(thebundle);    
    return myview;
    }


   protected static class MyviewHolder{
            protected ImageView theimageview;
               }

public class Thethreadasynctask extends AsyncTask<Bundle, Void,Integer> {
    Hashtable<Integer,Bitmap> theimagehashmap;

    @Override
    protected Integer doInBackground(Bundle... mybundle) {
        String mylocalurl=mybundle[0].getString("thelocalurl");
        Integer theposition=mybundle[0].getInt("theposition");
        URL themainurl=null;
        theimagehashmap=new Hashtable<Integer,Bitmap>();
        try{
            themainurl=new URL(myurl,mylocalurl);

        }catch (MalformedURLException es){
            es.printStackTrace();
        }
        try{
            HttpURLConnection myurlconnection=(HttpURLConnection)themainurl.openConnection();
            myurlconnection.setDoInput(true);
            myurlconnection.connect();
            InputStream is=myurlconnection.getInputStream();
            Bitmap bmImg=BitmapFactory.decodeStream(is);
            Bundle mylocalbundle=new Bundle();
            mylocalbundle.putParcelable("theimage",bmImg);
            mylocalbundle.putInt("thepos",theposition);
            theimagehashmap.put(theposition,bmImg);
        }catch(IOException e){
            Log.e("alice","ioexception");
        }
        return theposition;
    }
protected void onPostExecute(Integer myposition){
    Bitmap myimage=theimagehashmap.get(myposition);
    ImageView thegreatview=thegreatviewholders.get(myposition);
    thegreatview.setImageBitmap(myimage);
}

}}

错误: -

  1. 当我记录数组适配器的循环时,我看到它遍历三个元素的数组,如0,1,2,然后返回到0。
  2. 虽然数组中的元素只有3个
  3. ,但异步线程被调用了5次
  4. 显示的三个图像中只有2个显示..
  5. 有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

  1. 您无法控制刷新视图的次数以及重绘元素的次数。我认为这是从适配器多次请求元素的原因。
  2. 如第1点所述:如果多次请求元素,则异步任务将运行多次。
  3. 有些观点可能不会被绘制,因为它们已经被驳回。您不应该继续使用view元素,因为可以在异步任务进入Web时更改它。 如果您尝试显示大量元素,也可能最终在错误的位置看到错误的图像,因为网格中的视图可以重复使用。
  4. 我建议的是一种不同的机制,缓存弱引用的结果。返回一些结果后,只需刷新网格,图像将从缓存中获取 - 无需再次访问网络。这样您就不会保留网格的子视图 - 只需请求网格自行刷新。