[英]Android - AsyncTask - ListView Adapter
In short. 简而言之。 i have one asynctask, JSONReadTask that requests & a list of radio presenters.
我有一个asynctask,JSONReadTask请求和无线电演示者列表。 From this list an image reference is taken and passed to another Asyntask, ImageRetrival.
从该列表中获取图像参考,并将其传递给另一个Asyntask,即ImageRetrival。
i'm having difficulty working with the asynchronous of android whilst downloading images to a listview. 我在将图像下载到列表视图时遇到了与Android异步的问题。
I intially had the adapter settings with ListView.setAdapter() at the end of the JSONReadTask so once all the images were retrived, the list could then be populated. 我最初在JSONReadTask的末尾使用ListView.setAdapter()进行了适配器设置,因此一旦检索了所有图像,便可以填充列表。 however when setting the adapter for the listview, i kept getting NullPointerException of the data source of the adapter.
但是,当为列表视图设置适配器时,我一直在获取适配器数据源的NullPointerException。
What i require, and cannot get my head around is how to set the adapter to the list view, then somehow use notifyDataSetChanged() to update the list view as each imageRetrival PostExecutes. 我需要做的是如何将适配器设置为列表视图,然后以某种方式使用notifyDataSetChanged()更新每个imageRetrival PostExecutes时的列表视图。
public class Presenters extends Activity {
private String jsonResult;
private String url = "http://www.example.co.uk/Radio/api.php?q=Presenters";
public List<HashMap<String, Bitmap>> ImageList;
private ListView listView;
private ExtendedSimpleAdapter exad;
//private Bitmap[] images;
//private int counter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_presenters);
// Show the Up button in the action bar.
setupActionBar();
//counter = 0;
listView = (ListView) findViewById(R.id.listViewPres);
accessWebService();
}
/**
* Set up the {@link android.app.ActionBar}, if the API is available.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupActionBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.presenters, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
private class ImageRetrival extends AsyncTask<String, Void, Bitmap> {
private Bitmap btmp;
String id;
private String ImageUrl = "http://www.example.co.uk/RPUser/"; //Image Directory
// ///////////
// GET IMAGE//
// ///////////
protected Bitmap doInBackground(String... params) {
// download image to bitmap
try {
Log.d("URLparam", params[0]);
String u = ImageUrl + params[0];
URL url = new URL(u);
Log.d("URL:", "" + url);
// split arguments
// if(overView request)->continue;
// if(SpecificRequest)->explode(url, 'i')-> id;
/*
* if(url.toString().contains("q=") &&
* url.toString().contains("i=")){ String[] urlArray =
* url.toString().split("i=", 2); id = urlArray[1];
* Log.d("Url.Split>id", ""+id); }
*/
id = url.toString();
InputStream stream;
BufferedInputStream bis;
URLConnection ConUrl = url.openConnection();
HttpURLConnection htpcon = (HttpURLConnection) ConUrl;
htpcon.setRequestMethod("GET");
htpcon.setDoInput(true);
htpcon.connect();
if (htpcon.getResponseCode() != HttpURLConnection.HTTP_OK) {
Log.d("HTTP-ERROR", "" + htpcon.getResponseCode());
}
stream = htpcon.getInputStream();
bis = new BufferedInputStream(stream);
Log.d("Stream" + url, "" + stream);
btmp = BitmapFactory.decodeStream(bis);
Log.d("Bitmap-Code", "" + btmp);
stream.close();
} catch (IOException e) {
Log.d("Catch", "Issue Here");
e.printStackTrace();
}
return btmp;
}
protected void onPostExecute(Bitmap result) {
HashMap<String, Bitmap> table = new HashMap<String, Bitmap>();
table.put("Image", result);
Log.d("OnPost", ""+result);
ImageList.add(table); //Line 154 which returns NullPointer
exad = new ExtendedSimpleAdapter(Presenters.this,
ImageList, R.layout.listview_item_row_presenters, new String[]
{"Image", "Name", "About"}, new int[] {R.id.imgIcon, R.id.txtTitle,
R.id.txtAbout});
Log.d("PostExecute", "" + result);
listView.setAdapter(exad);
}
}
//
// Start JSON CODE
//
private class JsonReadTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
Log.d("JSON", "" + params[0]);
try {
HttpResponse responce = httpclient.execute(httppost);
jsonResult = inputStreamToString(
responce.getEntity().getContent()).toString();
Log.d("JSON", "" + jsonResult);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private StringBuilder inputStreamToString(InputStream is) {
String rLine = "";
StringBuilder answer = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((rLine = rd.readLine()) != null) {
answer.append(rLine);
}
}
catch (IOException e) {
// e.printStackTrace();
Toast.makeText(getApplicationContext(),
"Error..." + e.toString(), Toast.LENGTH_LONG).show();
}
return answer;
}
@Override
protected void onPostExecute(String result) {
ListDrwaer();
}
} // end Async Task extension
public void accessWebService() {
JsonReadTask task = new JsonReadTask();
// passes values for the urls string array
task.execute(new String[] { url });
}
// build hash set for list view
public void ListDrwaer() {
List<HashMap<String, String>> presenterlist = new ArrayList<HashMap<String, String>>();
try {
JSONObject jsonResponse = new JSONObject(jsonResult);
JSONArray jsonMainNode = jsonResponse.getJSONArray("Presenters");
for (int i = 0; i < jsonMainNode.length(); i++) {
JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);
String name = jsonChildNode.getString("FirstName");
String lastName = jsonChildNode.getString("LastName");
String fullName = name + " " + lastName;
String about = jsonChildNode.getString("About");
String image = jsonChildNode.getString("Image");
ImageRetrival getImage = new ImageRetrival();
getImage.execute(image);
Log.d("Progress", "Got Image " + image);
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("Name", fullName);
hm.put("About", about);
hm.put("Image", image);
presenterlist.add(hm);
}
} catch (JSONException e) {
Toast.makeText(getApplicationContext(),
"Error - JSON Retrival - HashMap" + e.toString(),
Toast.LENGTH_SHORT).show();
}
/*SimpleAdapter simpleAdapter = new SimpleAdapter(this, presenterlist,
R.layout.listview_item_row_presenters, new String[] { "Image",
"Name", "About" }, new int[] { R.id.imgIcon,
R.id.txtTitle, R.id.txtAbout });*/
if(ImageList == null){
Log.d("Report", "ImageListNULL");
}
else{
Log.d("Report", ""+ImageList);
}
listView.setAdapter(exad);//Currently throws nullPointerException of HashMap<String, Bitmap>
//listView.getAdapter().notifyDataSetChanged();//want to know how to utilise this
}
//
// End JSON Code
} }
The Extended Adapter: 扩展适配器:
public class ExtendedSimpleAdapter extends SimpleAdapter{
List<HashMap<String, Bitmap>> map;
String[] from;
int layout;
int[] to;
Context context;
LayoutInflater mInflater;
public ExtendedSimpleAdapter(Context context, List<HashMap<String, Bitmap>> data, int resource, String[] from, int[] to) {
super(context, data, resource, from, to);
layout = resource;
map = data;
this.from = from;
this.to = to;
this.context = context;
}
@Override
public int getCount(){
return map.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return this.createViewFromResource(position, convertView, parent, layout);
}
private View createViewFromResource(int position, View convertView,
ViewGroup parent, int resource) {
View v;
if (convertView == null) {
v = mInflater.inflate(resource, parent, false);
} else {
v = convertView;
}
this.bindView(position, v);
return v;
}
private void bindView(int position, View view) {
final Map dataSet = map.get(position);
if (dataSet == null) {
return;
}
final ViewBinder binder = super.getViewBinder();
final int count = to.length;
for (int i = 0; i < count; i++) {
final View v = view.findViewById(to[i]);
if (v != null) {
final Object data = dataSet.get(from[i]);
String text = data == null ? "" : data.toString();
if (text == null) {
text = "";
}
boolean bound = false;
if (binder != null) {
bound = binder.setViewValue(v, data, text);
}
if (!bound) {
if (v instanceof Checkable) {
if (data instanceof Boolean) {
((Checkable) v).setChecked((Boolean) data);
} else if (v instanceof TextView) {
// Note: keep the instanceof TextView check at the bottom of these
// ifs since a lot of views are TextViews (e.g. CheckBoxes).
setViewText((TextView) v, text);
} else {
throw new IllegalStateException(v.getClass().getName() +
" should be bound to a Boolean, not a " +
(data == null ? "<unknown type>" : data.getClass()));
}
} else if (v instanceof TextView) {
// Note: keep the instanceof TextView check at the bottom of these
// ifs since a lot of views are TextViews (e.g. CheckBoxes).
setViewText((TextView) v, text);
} else if (v instanceof ImageView) {
if (data instanceof Integer) {
setViewImage((ImageView) v, (Integer) data);
} else if (data instanceof Bitmap){
setViewImage((ImageView) v, (Bitmap)data);
} else {
setViewImage((ImageView) v, text);
}
} else {
throw new IllegalStateException(v.getClass().getName() + " is not a " +
" view that can be bounds by this SimpleAdapter");
}
}
}
}
}
private void setViewImage(ImageView v, Bitmap bmp){
v.setImageBitmap(bmp);
}
}
Thank you in advance 先感谢您
LogCat Output: LogCat输出:
05-27 13:56:19.010: E/AndroidRuntime(2861): FATAL EXCEPTION: main
05-27 13:56:19.010: E/AndroidRuntime(2861): java.lang.NullPointerException
05-27 13:56:19.010: E/AndroidRuntime(2861): at com.example.dev_app001.Presenters$ImageRetrival.onPostExecute(Presenters.java:154)
05-27 13:56:19.010: E/AndroidRuntime(2861): at com.example.dev_app001.Presenters$ImageRetrival.onPostExecute(Presenters.java:1)
05-27 13:56:19.010: E/AndroidRuntime(2861): at android.os.AsyncTask.finish(AsyncTask.java:631)
05-27 13:56:19.010: E/AndroidRuntime(2861): at android.os.AsyncTask.access$600(AsyncTask.java:177)
05-27 13:56:19.010: E/AndroidRuntime(2861): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
05-27 13:56:19.010: E/AndroidRuntime(2861): at android.os.Handler.dispatchMessage(Handler.java:99)
05-27 13:56:19.010: E/AndroidRuntime(2861): at android.os.Looper.loop(Looper.java:213)
05-27 13:56:19.010: E/AndroidRuntime(2861): at android.app.ActivityThread.main(ActivityThread.java:5225)
05-27 13:56:19.010: E/AndroidRuntime(2861): at java.lang.reflect.Method.invokeNative(Native Method)
05-27 13:56:19.010: E/AndroidRuntime(2861): at java.lang.reflect.Method.invoke(Method.java:525)
05-27 13:56:19.010: E/AndroidRuntime(2861): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:741)
05-27 13:56:19.010: E/AndroidRuntime(2861): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
05-27 13:56:19.010: E/AndroidRuntime(2861): at dalvik.system.NativeStart.main(Native Method)
You have 2 tasks JsonReadTask
and ImageRetrival
您有2个任务
JsonReadTask
和ImageRetrival
You run JsonReadTask
first, then onPostExecute
you run ImageRetrival
您首先运行
JsonReadTask
,然后在onPostExecute
运行ImageRetrival
The problem is you instantiate exad
only later ImageRetrival
. 问题是您仅在稍后实例化
exad
ImageRetrival
。
So calling listView.setAdapter(exad);
因此调用
listView.setAdapter(exad);
when ImageRetrival
is not finished will create problems since the tasks run asynchronously. 当
ImageRetrival
未完成时,由于任务异步运行,因此会产生问题。
I would say remove listView.setAdapter(exad);
我会说删除
listView.setAdapter(exad);
from JsonReadTask
since you call it already once ImageRetrival
finished executing. 从
JsonReadTask
调用,因为一旦ImageRetrival
完成执行,就已经调用了它。
You should avoid variable with class scope they can cause bugs and such null pointers. 您应该避免在类范围内使用变量,因为它们可能会导致错误以及此类空指针。
try to keep things as private as possible. 尽量将事情保密。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.