在手势监听器中调用AsyncTask时出错

时间:2014-06-03 19:01:41

标签: java android listview android-asynctask gesture

现在,我有一个Activity,显示来自JSON数组的10个列表。接下来,在ImageView的滑动中,我想要清除ListView并显示下一个10(作为"下一页"类型的东西)。所以,现在我这样做

    view.setOnTouchListener(new OnSwipeTouchListener(getBaseContext()) {
        @Override
        public void onSwipeLeft() {
                    //clear adapter
            adapter.clear();
                    //get listings 10-20
            startLoop = 10; 
            endLoop = 20;
                    //call asynctask to display locations
        FillLocations myFill = new FillLocations();
        myFill.execute();
        Toast.makeText(getApplicationContext(), "Left",
                       Toast.LENGTH_LONG).show();

        }

当我滑动它时显示一个项目我得到了这个错误 Error Parsing Data android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 我究竟做错了什么?谢谢!

完整代码:

public class MainActivity extends ActionBarActivity {

ListView listView;
int startLoop, endLoop;
TextView test;
ArrayList<Location> arrayOfLocations;
LocationAdapter adapter;

ImageView view;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    startLoop = 0;
    endLoop = 10;
    listView = (ListView) findViewById(R.id.listView1);

    // Construct the data source
    arrayOfLocations = new ArrayList<Location>();

    // Create the adapter to convert the array to views
    adapter = new LocationAdapter(this, arrayOfLocations);

    FillLocations myFill = new FillLocations();
    myFill.execute();

    view = (ImageView) findViewById(R.id.imageView1);

    view.setOnTouchListener(new OnSwipeTouchListener(getBaseContext()) {
        @Override
        public void onSwipeLeft() {
            adapter.clear();

            startLoop = 10;
            endLoop = 20;
        FillLocations myFill = new FillLocations();
        myFill.execute();
        Toast.makeText(getApplicationContext(), "Left",
                       Toast.LENGTH_LONG).show();

        }
    });

}

private class FillLocations extends AsyncTask<Integer, Void, String> {
    String msg = "Done";

    protected void onPreExecute() {
        progress.show();
    }

    // Decode image in background.
    @Override
    protected String doInBackground(Integer... params) {

        String result = "";
        InputStream isr = null;
        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("http://americanfarmstands.com/places/");
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            isr = entity.getContent();
            // resultView.setText("connected");
        } catch (Exception e) {
            Log.e("log_tag", "Error in http connection " + e.toString());
        }
        // convert response to string
        try {
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(isr, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            isr.close();

            result = sb.toString();
        } catch (Exception e) {
            Log.e("log_tag", "Error  converting result " + e.toString());
        }

        // parse json data
        try {
            JSONArray jArray = new JSONArray(result);

            for (int i = startLoop; i < endLoop; i++) {

                //Toast.makeText(getApplicationContext(), i,
                //         Toast.LENGTH_LONG).show();
                final JSONObject json = jArray.getJSONObject(i);
                // counter++;

                String initialURL = "http://afs.spotcontent.com/img/Places/Icons/";
                final String updatedURL = initialURL + json.getInt("ID")
                        + ".jpg";
                Bitmap bitmap2 = null;

                try {
                    bitmap2 = BitmapFactory
                            .decodeStream((InputStream) new URL(updatedURL)
                                    .getContent());

                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                try {
                    adapter.add(new Location(bitmap2, json
                            .getString("PlaceTitle"), json
                            .getString("PlaceDetails"), json
                            .getString("PlaceDistance"), json
                            .getString("PlaceUpdatedTime")));
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

        } catch (Exception e) {
            // TODO: handle exception
            Log.e("log_tag", "Error Parsing Data " + e.toString());
        }
        return msg;

    }

    protected void onPostExecute(String msg) {
        // Attach the adapter to a ListView
        //ListView listView = (ListView) findViewById(R.id.listView1);

        listView.setAdapter(adapter);

        progress.dismiss();

    }
}

位置适配器:

public class LocationAdapter extends ArrayAdapter<Location> {
public LocationAdapter(Context context, ArrayList<Location> locations) {
   super(context, R.layout.item_location, locations);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
   // Get the data item for this position
   Location location = getItem(position);    
   // Check if an existing view is being reused, otherwise inflate the view
   if (convertView == null) {
      convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_location, parent, false);
   }

   // Lookup view for data population
   TextView tvName = (TextView) convertView.findViewById(R.id.tvName);
   TextView tvDetails = (TextView) convertView.findViewById(R.id.tvDetails);
   TextView tvDistance = (TextView) convertView.findViewById(R.id.tvDistance);
   TextView tvHours = (TextView) convertView.findViewById(R.id.tvHours);
   ImageView ivIcon = (ImageView) convertView.findViewById(R.id.imgIcon);

   // Populate the data into the template view using the data object
   tvName.setText(location.name);
   tvDetails.setText(location.details);
   tvDistance.setText(location.distance);
   tvHours.setText(location.hours);
   ivIcon.setImageBitmap(location.icon);
   // Return the completed view to render on screen
   return convertView;
}
}

编辑:更新代码:

for(int i = startLoop; i&lt; endLoop; i ++){

                // Toast.makeText(getApplicationContext(), i,
                // Toast.LENGTH_LONG).show();
                final JSONObject json = jArray.getJSONObject(i);
                // counter++;

                String initialURL = "http://afs.spotcontent.com/img/Places/Icons/";
                final String updatedURL = initialURL + json.getInt("ID")
                        + ".jpg";
                final Bitmap bitmap2 =BitmapFactory
                        .decodeStream((InputStream) new URL(updatedURL)
                        .getContent());

                //try {
                //  bitmap2 = BitmapFactory
                //          .decodeStream((InputStream) new URL(updatedURL)
                //                  .getContent());

                //} catch (MalformedURLException e) {
                //  e.printStackTrace();
                //} catch (IOException e) {
                //  e.printStackTrace();
                //}
                MainActivity.this.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            adapter.add(new Location(bitmap2, json
                                    .getString("PlaceTitle"), json
                                    .getString("PlaceDetails"), json
                                    .getString("PlaceDistance"), json
                                    .getString("PlaceUpdatedTime")));
                        } catch (JSONException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                    }
                });

            }

3 个答案:

答案 0 :(得分:1)

该错误清楚地表明您正在尝试从捕获异常doInBackground的其他线程(CalledFromWrongThreadException)更新View。

此行是问题的原因

adapter.add(new Location(bitmap2, json .getString("PlaceTitle"), json .getString("PlaceDetails"), json .getString("PlaceDistance"), json .getString("PlaceUpdatedTime")));

它应该在主线程中调用。

<强>溶液

调用主线程并从那里更新适配器

示例:

try {
                   final Bitmap bitmap2 = BitmapFactory
                            .decodeStream((InputStream) new URL(updatedURL)
                                    .getContent());
MainActivity.this.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                adapter.add(new Location(bitmap2, json
                            .getString("PlaceTitle"), json
                            .getString("PlaceDetails"), json
                            .getString("PlaceDistance"), json
                            .getString("PlaceUpdatedTime")));

            }
        });

                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

答案 1 :(得分:1)

必须从 UI线程更新适配器。

您应该将AsyncTask更改为AsyncTask<Integer, Void, List<Location>>,然后让doInBackground()上的循环创建一个Location返回的集合(而不是直接更改)适配器)。

最后,在onPostExecute(List<Location> result)中,执行:

adapter.clear();
for (Location location : result)
    adapter.add(location);

答案 2 :(得分:0)

将这一堆代码移至onPostExecute

protected void onPostExecute(String msg) {
    try {
            adapter.add(new Location(bitmap2, json
                    .getString("PlaceTitle"), json
                    .getString("PlaceDetails"), json
                    .getString("PlaceDistance"), json
                    .getString("PlaceUpdatedTime")));
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    // Attach the adapter to a ListView
    //ListView listView = (ListView) findViewById(R.id.listView1);

    listView.setAdapter(adapter);

    progress.dismiss();
}

使Bitmap成为一个类变量。