只有创建视图层次结构的原始线程才能触及其视图异常[重复]
Posted
技术标签:
【中文标题】只有创建视图层次结构的原始线程才能触及其视图异常[重复]【英文标题】:Only the original thread that created a view hierarchy can touch its views exception [duplicate] 【发布时间】:2014-01-17 08:58:52 【问题描述】:这个类有一个例外:“只有创建视图层次结构的原始线程才能接触它的视图”。
我知道这可能是我使用异步的事实,但我是 android dev 的新手,即使阅读 *** 上的其他案例,我也没有设法安排它。欢迎帮忙!
我的班级:
package com.test.example;
import java.util.ArrayList;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageButton;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
public class ShopsActivity extends Activity
private ProgressDialog pDialog;
// URL to get contacts JSON
private static String url = "mywebserviceurl";
// JSON Node names
private static final String TAG_NAME = "shop_name";
private static final String TAG_ADDRESS_STRING = "shop_address";
TextView shop_address;
TextView shop_name;
TextView api;
private ListView list;
private ImageButton button1;
private ImageButton button2;
private ImageButton button3;
private ImageButton button4;
// contacts JSONArray
JSONArray contacts = null;
// Hashmap for ListView
ArrayList<HashMap<String, String>> oslist = new ArrayList<HashMap<String, String>>();
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shops);
// Calling async task to get json
new GetJson().execute();
/**
* Async task class to get json by making HTTP call
* */
private class GetJson extends AsyncTask<Void, Void, Void>
@Override
protected void onPreExecute()
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(ShopsActivity.this);
pDialog.setMessage("Mise à jour...");
pDialog.setCancelable(false);
pDialog.show();
@Override
protected Void doInBackground(Void... arg0)
// Creating service handler class instance
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
JSONArray array = null;
try
array = new JSONArray(jsonStr);
catch (JSONException e1)
// TODO Auto-generated catch block
e1.printStackTrace();
try
for (int i = 0; i <array.length(); i++)
JSONObject jsonObject = array.getJSONObject(i);
String id = jsonObject.getString("id");
System.out.println("id --->" + id);
String url = jsonObject.getString("url");
System.out.println("url --->" + url);
String created_at = jsonObject.getString("created_at");
System.out.println("created_at --->" + created_at);
String updated_at = jsonObject.getString("updated_at");
System.out.println("updated_at --->" + updated_at);
String name = jsonObject.getString("name");
System.out.println("name --->" + name);
JSONArray photos_urls = jsonObject.getJSONArray("photos_urls");
System.out.println("photos_urls --->" + photos_urls);
String address_string = jsonObject.getString("address_string");
System.out.println("address_string --->" + address_string);
JSONObject booklet = jsonObject.getJSONObject("booklet");
String id_booklet = booklet.getString("id");
System.out.println("id_booklet --->" + id_booklet);
String url_booklet = booklet.getString("url");
System.out.println("url_booklet --->" + url_booklet);
String created_at_booklet = booklet.getString("created_at");
System.out.println("created_at_booklet --->" + created_at_booklet);
String updated_at_booklet = booklet.getString("updated_at");
System.out.println("updated_at_booklet --->" + updated_at_booklet);
String document_url = booklet.getString("document_url");
System.out.println("document_url --->" + document_url);
String presented = booklet.getString("presented");
System.out.println("presented --->" + presented);
// Adding value HashMap key => value
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_NAME, name);
map.put(TAG_ADDRESS_STRING, address_string);
oslist.add(map);
list=(ListView)findViewById(R.id.list);
ListAdapter adapter = new SimpleAdapter(ShopsActivity.this, oslist,
R.layout.listview_item_row,
new String[] TAG_NAME, TAG_ADDRESS_STRING , new int[]
R.id.name_shop, R.id.address_shop);
list.setAdapter(adapter);
/* list.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id)
Intent intent = new Intent(ShopsActivity.this, ShopActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.animationin, R.anim.animationout);
);*/
catch (JSONException e)
e.printStackTrace();
return null;
@Override
protected void onPostExecute(Void result)
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
这是我尝试使用 onPostExecute 后的日志:
12-30 14:10:28.515: E/AndroidRuntime(12951): FATAL EXCEPTION: AsyncTask #1
12-30 14:10:28.515: E/AndroidRuntime(12951): java.lang.RuntimeException: An error occured while executing doInBackground()
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.os.AsyncTask$3.done(AsyncTask.java:299)
12-30 14:10:28.515: E/AndroidRuntime(12951): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
12-30 14:10:28.515: E/AndroidRuntime(12951): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
12-30 14:10:28.515: E/AndroidRuntime(12951): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
12-30 14:10:28.515: E/AndroidRuntime(12951): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
12-30 14:10:28.515: E/AndroidRuntime(12951): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
12-30 14:10:28.515: E/AndroidRuntime(12951): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
12-30 14:10:28.515: E/AndroidRuntime(12951): at java.lang.Thread.run(Thread.java:856)
12-30 14:10:28.515: E/AndroidRuntime(12951): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4609)
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:867)
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.view.ViewGroup.invalidateChild(ViewGroup.java:4066)
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.view.View.invalidate(View.java:10250)
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.view.View.invalidate(View.java:10205)
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.widget.AbsListView.resetList(AbsListView.java:1952)
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.widget.ListView.resetList(ListView.java:502)
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.widget.ListView.setAdapter(ListView.java:442)
12-30 14:10:28.515: E/AndroidRuntime(12951): at com.begital.votrebijoutier.ShopsActivity$GetJson.doInBackground(ShopsActivity.java:141)
12-30 14:10:28.515: E/AndroidRuntime(12951): at com.begital.votrebijoutier.ShopsActivity$GetJson.doInBackground(ShopsActivity.java:1)
12-30 14:10:28.515: E/AndroidRuntime(12951): at android.os.AsyncTask$2.call(AsyncTask.java:287)
12-30 14:10:28.515: E/AndroidRuntime(12951): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
12-30 14:10:28.515: E/AndroidRuntime(12951): ... 5 more
12-30 14:10:28.975: E/WindowManager(12951): Activity com.begital.votrebijoutier.ShopsActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@419962f8 that was originally added here
12-30 14:10:28.975: E/WindowManager(12951): android.view.WindowLeaked: Activity com.begital.votrebijoutier.ShopsActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@419962f8 that was originally added here
12-30 14:10:28.975: E/WindowManager(12951): at android.view.ViewRootImpl.<init>(ViewRootImpl.java:374)
12-30 14:10:28.975: E/WindowManager(12951): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:292)
12-30 14:10:28.975: E/WindowManager(12951): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
12-30 14:10:28.975: E/WindowManager(12951): at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
12-30 14:10:28.975: E/WindowManager(12951): at android.view.Window$LocalWindowManager.addView(Window.java:547)
12-30 14:10:28.975: E/WindowManager(12951): at android.app.Dialog.show(Dialog.java:277)
12-30 14:10:28.975: E/WindowManager(12951): at com.begital.votrebijoutier.ShopsActivity$GetJson.onPreExecute(ShopsActivity.java:77)
12-30 14:10:28.975: E/WindowManager(12951): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
12-30 14:10:28.975: E/WindowManager(12951): at android.os.AsyncTask.execute(AsyncTask.java:534)
12-30 14:10:28.975: E/WindowManager(12951): at com.begital.votrebijoutier.ShopsActivity.onCreate(ShopsActivity.java:61)
12-30 14:10:28.975: E/WindowManager(12951): at android.app.Activity.performCreate(Activity.java:5008)
12-30 14:10:28.975: E/WindowManager(12951): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
12-30 14:10:28.975: E/WindowManager(12951): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
12-30 14:10:28.975: E/WindowManager(12951): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
12-30 14:10:28.975: E/WindowManager(12951): at android.app.ActivityThread.access$600(ActivityThread.java:130)
12-30 14:10:28.975: E/WindowManager(12951): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
12-30 14:10:28.975: E/WindowManager(12951): at android.os.Handler.dispatchMessage(Handler.java:99)
12-30 14:10:28.975: E/WindowManager(12951): at android.os.Looper.loop(Looper.java:137)
12-30 14:10:28.975: E/WindowManager(12951): at android.app.ActivityThread.main(ActivityThread.java:4745)
12-30 14:10:28.975: E/WindowManager(12951): at java.lang.reflect.Method.invokeNative(Native Method)
12-30 14:10:28.975: E/WindowManager(12951): at java.lang.reflect.Method.invoke(Method.java:511)
12-30 14:10:28.975: E/WindowManager(12951): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
12-30 14:10:28.975: E/WindowManager(12951): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
12-30 14:10:28.975: E/WindowManager(12951): at dalvik.system.NativeStart.main(Native Method)
12-30 14:10:31.905: I/Process(12951): Sending signal. PID: 12951 SIG: 9
【问题讨论】:
总是发布你的 logcat/stacktrace,它有助于解决问题。 【参考方案1】:UI 修改仅在 Ui 线程中完成。您正在更新您的 ListView 中的 doInbackGround
() 方法,该方法在不同的线程中运行..更改您的代码,如下所示..
runOnUiThread(new Runnable()
@Override
public void run()
list.setAdapter(adapter);
);
或者在AsynchTask
的onPostExecute
()方法中更新listview就好了..
@Override
protected void onPostExecute(Void result)
super.onPostExecute(result);
list = (ListView) findViewById(R.id.list);
ListAdapter adapter = new SimpleAdapter(ShopsActivity.this, oslist,
R.layout.listview_item_row, new String[] TAG_NAME,
TAG_ADDRESS_STRING , new int[] R.id.name_shop,
R.id.address_shop );
list.setAdapter(adapter);
【讨论】:
好的,我试过了,但还是有异常,我会在几秒钟内上传我的日志。 它不会给出任何异常..将您的完整日志发布一次.. 放置这个list.setAdapter(adapter);正如我上面所说,在 runonUiThread 内部..并尝试.. 好吧,我的错误没有例外。但是现在我的列表视图是空白的。 这意味着您的 SimpleAdapter getView() 方法有问题..检查一次..【参考方案2】:将此代码放入 onPostExecute
> HashMap<String, String> map = new HashMap<String, String>();
> map.put(TAG_NAME, name);
> map.put(TAG_ADDRESS_STRING, address_string);
> oslist.add(map);
> list=(ListView)findViewById(R.id.list);
> ListAdapter adapter = new SimpleAdapter(ShopsActivity.this, oslist,
> R.layout.listview_item_row,
> new String[] TAG_NAME, TAG_ADDRESS_STRING , new int[]
> R.id.name_shop, R.id.address_shop);
> list.setAdapter(adapter);
【讨论】:
【参考方案3】:您不能在后台线程中更改或访问 ui 元素。由于您的 listview setadapter 方法而出错。
ListAdapter adapter = new SimpleAdapter(ShopsActivity.this, oslist,
R.layout.listview_item_row, new String[] TAG_NAME,TAG_ADDRESS_STRING,
new int[]
R.id.name_shop, R.id.address_shop
);
list.setAdapter(adapter);
【讨论】:
以上是关于只有创建视图层次结构的原始线程才能触及其视图异常[重复]的主要内容,如果未能解决你的问题,请参考以下文章
只有创建视图层次结构的原始线程才能接触其视图。在安卓上[重复]
Android 错误“只有创建视图层次结构的原始线程才能触摸其视图”
致命例外:JavaBridge - 只有创建视图层次结构的原始线程才能接触其视图
android.view.ViewRootImpl $CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸其视图[重复]