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

发布于 2024-12-27 20:00:06 字数 3893 浏览 2 评论 0原文

我刚刚开始在 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);
}

}}

bugs:-

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

有人可以帮忙吗?

I am just beginning to work on android and seems like I have got into some multi threading issues. Could someone please have a look at the code below and tell me what all am i doing wrong here.

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

}}

The asyncadapter is as below:-

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

}}

The bugs:-

  1. When I log the looping of the array adapter, I see it traverses the array of three elements like 0,1,2 and then back to 0.
  2. The async thread is being called 5 times although the elements in the array are only 3
  3. Out of the three images which are supposed to be displayed only 2 are shown..

Can someone please help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

初见终念 2025-01-03 20:00:06
  1. 您无法控制刷新视图和重绘元素的次数。我认为这就是适配器多次请求元素的原因。
  2. 如第 1 点:如果多次请求元素,则异步任务将运行多次。
  3. 有些观点可能不会被提出,因为它们已经被驳回了。您不应该保留视图元素,因为它可以在异步任务访问网络时更改。
    如果您尝试显示大量元素,您也可能最终会在错误的位置看到错误的图像,因为网格中的视图可以重复使用。

我建议采用一种不同的机制来缓存弱引用中的结果。返回一些结果后,只需刷新网格,图像就会从缓存中获取 - 无需再次访问网络。这样您就不会保留网格的子视图 - 只需请求网格刷新自身。

  1. You don't control the number of times a view is refreshed and the elements are redrawn. I think that is the reason the elements are requested several times from the adapter.
  2. As in point 1: if the elements are requested several times, the async task will run several times.
  3. Some of the views may not be drawn because they have been already dismissed. You should not hold on to the the view element, because it can be changed while the async task is going to the web.
    If you try showing lots of elements, you also may end up seeing the wrong image in the wrong position, because the views in the grid can be reused.

What I would suggest is a different mechanism that caches the results in weak references. Once some results are returned, just refresh the grid and the images will be taken from the cache - without going once again to the web. This way you do not keep the sub-view of the grid - just request the grid to refresh itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文