Android - AsyncTask - ListView适配器

时间:2014-05-27 12:54:09

标签: android json listview android-asynctask

简而言之。 我有一个asynctask,JSONReadTask请求&电台节目主持人名单。 从此列表中获取图像引用并将其传递给另一个Asyntask,ImageRetrival。

在将图像下载到列表视图时,我很难使用android的异步。

我最初在JSONReadTask的末尾有ListView.setAdapter()的适配器设置,所以一旦所有图像都被重新检索,就可以填充列表。但是当为listview设置适配器时,我不断获得适配器数据源的NullPointerException。

我需要什么,无法理解的是如何将适配器设置为列表视图,然后以某种方式使用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

}

扩展适配器:

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);
} 
}

提前谢谢

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)

1 个答案:

答案 0 :(得分:0)

您有2个任务JsonReadTaskImageRetrival

首先运行JsonReadTask,然后onPostExecute运行ImageRetrival

问题是您只能在exad之后实例化ImageRetrival

因此,listView.setAdapter(exad);未完成时调用ImageRetrival会产生问题,因为任务是异步运行的。

我想从listView.setAdapter(exad);移除JsonReadTask,因为您已经ImageRetrival完成执行后调用它。

你应该避免使用类范围的变量,它们可能导致错误和这样的空指针。

尽量保持私密性。