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?
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.