现在,我有一个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();
}
}
});
}
答案 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
成为一个类变量。