Reputation: 1418
I am attempting to brush up on my android for a project at work, and it seams that im more out of touch than i first thought.
I am creating an app that uploads pictures to a remote server and then shows these uploads as thumbnails.
The section i am struggling is with downloading the image and applying it to the image view within a list view.
Im receiving a Null Pointer Exception which is never nice.
Im not sure if this is due to me starting a number of ASync tasks (one for each image) or if its something more obvious
Stack Trace
Process: com.example.alex.documentupload, PID: 5788
java.lang.NullPointerException
at com.example.alex.documentupload.DownloadImageTask.onPostExecute(DownloadImage.java:35)
at com.example.alex.documentupload.DownloadImageTask.onPostExecute(DownloadImage.java:14)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5748)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
Android Code Show images Class
package com.example.alex.documentupload;
import java.util.ArrayList;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import com.example.alex.documentupload.JSONParser;
import com.example.alex.documentupload.DownloadImageTask;
public class ShowImages extends Activity {
ListView list;
TextView ver;
TextView name;
TextView api;
ImageView img;
Button Btngetdata;
ArrayList<HashMap<String, String>> oslist = new ArrayList<HashMap<String, String>>();
//URL to get JSON Array
private static String url = "http://www.500kgiveaway.co.uk/getimagesmob.php";
//JSON Node Names
private static final String TAG_PATH = "path";
JSONArray android = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_images);
oslist = new ArrayList<HashMap<String, String>>();
new JSONParse().execute();
Btngetdata = (Button)findViewById(R.id.getdata);
Btngetdata.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// clear the list before adding more
//update the list
new JSONParse().execute();
}
});
}
private class JSONParse extends AsyncTask<String, String, JSONArray> {
private ProgressDialog pDialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
ver = (TextView)findViewById(R.id.vers);
name = (TextView)findViewById(R.id.name);
api = (TextView)findViewById(R.id.api);
img = (ImageView)findViewById(R.id.img);
pDialog = new ProgressDialog(ShowImages.this);
pDialog.setMessage("Getting Data ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
@Override
protected JSONArray doInBackground(String... args) {
JSONParser jParser = new JSONParser();
// Getting JSON from URL
JSONArray json = jParser.getJSONFromUrl(url);
return json;
}
@Override
protected void onPostExecute(JSONArray json) {
pDialog.dismiss();
try {
// Getting JSON Array from URL
android = json;
for(int i = 0 ; i < android.length(); i++){
JSONObject c = android.getJSONObject(i);
// Storing JSON item in a Variable
String path = c.getString(TAG_PATH);
// Adding value HashMap key => value
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_PATH, path);
oslist.add(map);
list=(ListView)findViewById(R.id.list);
ListAdapter adapter = new SimpleAdapter(ShowImages.this, oslist,
R.layout.list_v,
new String[] { TAG_PATH }, new int[] {
R.id.vers});
list.setAdapter(adapter);
new DownloadImageTask((ImageView) list.findViewById(R.id.img))
.execute("http://www.500kgiveaway.co.uk/" + path);
// list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//
// @Override
// public void onItemClick(AdapterView<?> parent, View view,
// int position, long id) {
// Toast.makeText(ShowImages.this, "You Clicked at "+oslist.get(+position).get("name"), Toast.LENGTH_SHORT).show();
// }
// });
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void loadcamera(View view) {
// Do something in response to button
Intent myIntent = new Intent(ShowImages.this, MainActivity.class);
myIntent.putExtra("dir", "BS"); //Optional parameters
ShowImages.this.startActivity(myIntent);
}
}
DownloadImages Class
package com.example.alex.documentupload;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
import java.io.InputStream;
/**
* Created by Alex on 03/05/2015.
*/
class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
Upvotes: 1
Views: 417
Reputation: 1418
This turned out to be a bit of a tricky fix, but got there in the end.
The issue was that i was unable to reference the imageview object inside the listview object whilst using a SimpleAdaptor.
The answer is that you need to create a custom class that extends SimpleAdaptor
I ended up using the picasso library, not because it helped fix the problem, more that it offered some image processing features, like resize etc which i had not previously allowed for.
I followed this answer Android - How can diplay pictures in a simpleApapter list view
However i run in to additional issues with context.
Here is my custom class that extends SimpleAdaptor
package com.example.alex.documentupload;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import com.squareup.picasso.Picasso;
import java.util.List;
import java.util.Map;
public class ExtendedAdaptor extends SimpleAdapter {
public static Context NewContext;
public ExtendedAdaptor(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to){
super(context, data, resource, from, to);
NewContext = context;
}
public View getView(int position, View convertView, ViewGroup parent){
// here you let SimpleAdapter built the view normally.
View v = super.getView(position, convertView, parent);
// Then we get reference for Picasso
ImageView img = (ImageView) v.getTag();
if(img == null){
img = (ImageView) v.findViewById(R.id.img);
v.setTag(img); // <<< THIS LINE !!!!
}
// get the url from the data you passed to the `Map`
String url = ((Map)getItem(position)).get("path").toString();
// do Picasso
// maybe you could do that by using many ways to start
Picasso.with(NewContext).load(url)
.resize(100, 100).into(img);
// return the view
return v;
}
}
and here is how i called it
ListView list = (ListView) findViewById(R.id.list);
ListAdapter adapter =
new ExtendedAdaptor(
context,
oslist,
R.layout.list_v,
new String[]{TAG_PATH},
new int[]{R.id.vers});
list.setAdapter(adapter);
Its all works pretty well, the image cache and image only download if they change.
I hope this helps someone else in the future
Thanks to all that contributed
Upvotes: 1