2012-01-19 30 views
1

我刚刚开始在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. 异步线程被调用5次,虽然数组中的元素只有3个
  3. 在应显示的三张图像中只显示了两张..

有人可以帮忙吗?

+0

只是一个声明,它在java中的习惯是,第一个单词是小写字母,其余的单词是大写的..就像myLocalBundle。和成员变量(全局变量)标记为mWhateverYouLike。 – JoxTraex

+0

关于bug 3,可能这可能是其中一个返回的图像为null。 – JoxTraex

+0

此外,您可能想要重写getCount()以查看传入的是哪个数字。这会让您知道它是否存在初始适配器数据或其他问题。 – JoxTraex

回答

0
  1. 您不控制刷新视图和重绘元素的次数。我认为这就是从适配器多次请求元素的原因。
  2. 如第1点所示:如果多次请求元素,则异步任务将运行多次。
  3. 有些意见可能不会被绘制,因为它们已被解雇。您不应该坚持视图元素,因为它可以在异步任务进入网页时进行更改。 如果您尝试显示大量元素,则最终可能会在错误的位置看到错误的图像,因为网格中的视图可以重复使用。

我会建议的是一个不同的机制,缓存在弱引用的结果。一旦返回一些结果,只需刷新网格并从缓存中获取图像 - 无需再次访问网页。这样你就不会保留网格的子视图 - 只需要网格刷新自己。

+0

感谢您的回答@ kilaka – Rasmus

+0

欢迎。我有同样的问题,并乐意帮助别人节省一些时间。 –

相关问题