使用asynctask和适配器显示远程图像android
我刚刚开始在 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:-
- 当我记录数组适配器的循环时,我看到它遍历了三个元素的数组,如 0,1,2,然后返回到 0。
- 异步线程被调用 5 次虽然数组中的元素只有 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:-
- 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.
- The async thread is being called 5 times although the elements in the array are only 3
- Out of the three images which are supposed to be displayed only 2 are shown..
Can someone please help?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您尝试显示大量元素,您也可能最终会在错误的位置看到错误的图像,因为网格中的视图可以重复使用。
我建议采用一种不同的机制来缓存弱引用中的结果。返回一些结果后,只需刷新网格,图像就会从缓存中获取 - 无需再次访问网络。这样您就不会保留网格的子视图 - 只需请求网格刷新自身。
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.