【问题标题】:Android - Can't create handler inside thread that has not called Looper.prepare()Android - 无法在未调用 Looper.prepare() 的线程内创建处理程序
【发布时间】:2013-09-09 19:55:49
【问题描述】:

我正在使用 Google Maps V2 API 开发一个简单的应用程序,只是为了了解基础知识,但我遇到了这个错误:

09-09 21:21:41.154: E/AndroidRuntime(3796): FATAL EXCEPTION: Thread-441
09-09 21:21:41.154: E/AndroidRuntime(3796): java.lang.ExceptionInInitializerError
09-09 21:21:41.154: E/AndroidRuntime(3796):  at cz.vongrad.dataSourceLayer.DataMapper.loadLocation(DataMapper.java:111)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at cz.vongrad.dataSourceLayer.DBFacade.loadLocations(DBFacade.java:32)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at cz.vongrad.domainLayer.Controller.loadLocations(Controller.java:94)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at cz.vongrad.locator.MapActivity$1.run(MapActivity.java:199)
09-09 21:21:41.154: E/AndroidRuntime(3796): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
09-09 21:21:41.154: E/AndroidRuntime(3796):  at android.os.Handler.<init>(Handler.java:121)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:607)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:607)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at android.os.AsyncTask.<clinit>(AsyncTask.java:190)
09-09 21:21:41.154: E/AndroidRuntime(3796):  ... 4 more
09-09 21:21:41.164: E/EmbeddedLogger(239): App crashed!

数据映射器:

class LoadLocations extends AsyncTask<String, Void, ArrayList<Friend>>{

        private JSONObject jSONObject;


        @Override
        protected ArrayList<Friend> doInBackground(String... args) {

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("user_name", args[1]));

            jSONObject = jSONParser.makeHttpRequest(args[0], "POST", params);
            Log.d(TAG, jSONObject.toString());

            ArrayList<Friend> tempFriends = new ArrayList<Friend>();

            try {
                if(jSONObject.getInt("success") == 1){

                    JSONArray jsonArray = jSONObject.getJSONArray("users");


                    for (int i = 0; i < jsonArray.length(); i++) {
                        JSONObject o = jsonArray.getJSONObject(i);

                        tempFriends.add(new Friend(o.getString("user_name"), new LatLng(o.getDouble("loc_y"), o.getDouble("loc_x")), false));
                    }

                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return tempFriends;
        }

    }

public ArrayList<Friend> loadLocation(String URL, String userName) throws InterruptedException, ExecutionException {
        return new LoadLocations().execute(URL, userName).get();

    }

地图活动:

public class MapActivity extends Activity implements LocationSource, LocationListener {
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
}
private Thread loadFriendLocations = new Thread()
    {

        @Override
        public void run() {
            Log.d(TAG, "LastKnownLocation: " + locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
            try {
                while(true) {
                    controller.loadLocations(LOAD_LOCATIONS);
                    Log.d(TAG, "Loading new locations");
                    Message msg = uIHandler.obtainMessage();
                    msg.what = ADD_MAP_PIN;
                    uIHandler.sendMessage(msg);

                    sleep(10000);                   
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

    final Handler uIHandler = new Handler(){
      @Override
      public void handleMessage(Message msg) {

        if(msg.what==ADD_MAP_PIN){

            for (Friend friend : controller.getFriends()) {

                    addMapPin(friend);


            }
        }
        super.handleMessage(msg);
      }
    };

奇怪的是,我可以在我的模拟器(API 16)上运行这个应用程序,它运行得很好,但是当我尝试在物理设备上运行它时(API 15),它得到了这个错误。 AsyncTask 在单独的类中运行,因此可能会导致此问题。我将不胜感激任何建议。提前致谢。

【问题讨论】:

标签: android android-asynctask


【解决方案1】:

我有一个类似的问题,问题是我有一系列来自主线程的线程。实际上,主 UI 线程启动了一个服务,该服务在一个服务上运行,随后又启动了另一个线程,该线程最终有了一个 FileObserver(另一个线程),我不得不通过弹出一条 toast 消息与 UI 线程进行通信。我试了几个小时,在下面试了试,效果很好。

//Let this be the code in your n'th level thread from main UI thread
Handler h = new Handler(Looper.getMainLooper());
h.post(new Runnable() {
  public void run() {
    Toast.makeText(context, "Your message to main thread", Toast.LENGTH_SHORT).show();
  }
});

这里的主要关键是 Looper 类的 getMainLooper() 函数,它将为您提供针对主 UI 线程的 Looper。

【讨论】:

  • 对于我的,当我将代码放入 run 方法时,它不会被执行。我该怎么办??
【解决方案2】:

您不能从后台线程执行AsyncTask。请参阅the AsyncTask documentation 的“线程规则”部分。

【讨论】:

  • 那么你认为如果我在 MapActivity 中的线程使用处理程序来执行 AsyncTask,它会工作吗?或者这是一个坏主意,我应该以完全不同的方式来做......?
  • @Husky:坦率地说,整个加载朋友位置的东西有点吓人。话虽如此,由于您已经在后台线程上,因此您不需要AsyncTask——只需完成工作即可。
  • 我想使用 AsyncTask 执行此操作的原因是我执行了一个无法在主线程中执行的网络操作,因此我必须在 AsyncTask 中执行此操作。顺便说一句,没有 AsyncTask 有什么办法吗??
  • @Husky:我再说一遍:你已经有一个后台线程。而不是从后台线程启动AsyncTask只需在现有后台线程上执行工作。如果出于某种原因您确实希望它位于其他后台线程上,请使用Thread
  • 我做了几层,我想在最低层从服务器加载数据(目前由AsyncTask完成),然后使用return语句将数据传回。问题是什么会更有效率,将当前在 MapActivity 中的线程放置到最低层并从那里执行持续加载,这将根据我的结构导致更高的耦合(保留对存储所有数据的 Controller 的引用)断绝)?当我使用 MapActivity 中的线程完成工作时,它会引发错误:NetworkOnMainThreadException
【解决方案3】:

在后台执行此操作...

runOnUiThread(new Runnable() {
    public void run() 
    {
        if (items.equals("null")) 
        {
            Toast.makeText(getApplicationContext(), "No Event Found",Toast.LENGTH_LONG).show();
        }                   
        else {                       
        }   
    }
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多