简体   繁体   English

Android-AsyncTask-ListView适配器

[英]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个任务JsonReadTaskImageRetrival

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM