Android: Only the original thread that created a view hierarchy can touch its views 異常


最近自己再寫一個小項目練手,創建一個線程從網絡獲取數據然后顯示在 recyclerView 上。寫好后發現頁面能夠顯示,但是有時候會把請求的數據顯示過來,有時候不會。點開 android monitor 一看,有一個提示 :

Only the original thread that created a view hierarchy can touch its views.

異常的意思是說只有創建這個view的線程才能操作這個 view,普通會認為是將view創建在非UI線程中才會出現這個錯誤。

本來我想將就下,能看到算了的,說明我會簡單使用 fragment 了。不過作為程序員我們肯定要尋根問底的啊。

這段請求數據代碼如下所示:

new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String url = "";
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder().url(url).method("GET", null).build();
                    okhttp3.Response response = client.newCall(request).execute();
                    if (response.isSuccessful()) {
                        String responseString = (response.body() == null ? "" : response.body().string());
                        ......解析數據
                        WidgetActionEvent event = new WidgetActionEvent(WidgetActionEvent.ACTION_CLICK);
                        event.object = feedModel;
                        EventBus.getDefault().post(event);
                        //iLoadData.loadData(feedModel);

                    } else {
                        Log.i(TAG, "okHttp is request error");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

數據請求之后,解析,並采用 eventbus 來傳送數據。

ps :如果你是在 mainActivity 中調用上述代碼,是不會產生的異常的,因為都是運行在主線程中。

變形一  : 崩潰

於是我換了一種形式來傳遞數據,這次采用回調的方式,也就是上面被注釋掉的那行代碼:

iLoadData.loadData(feedModel);

這次不用 eventbus 竟然崩潰了......我能怎么辦,我也很無奈啊。

FATAL EXCEPTION: Thread-932
Process: example.hope.mvpwithrecyclerview, PID: 4916
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

 

解決辦法:采用 handle 

實現代碼如下:

   /**
     * 發起網絡請求
     */
    public static void okHttp_synchronousGet(final Handler handler) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String url = "url";
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder().url(url).method("GET", null).build();
                    okhttp3.Response response = client.newCall(request).execute();
                    if (response.isSuccessful()) {
                        String responseString = (response.body() == null ? "" : response.body().string());
                        ......解析數據
                        handler.sendMessage(handler.obtainMessage(22, feedModel));
                    } else {
                        Log.i(TAG, "okHttp is request error");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

然后再 fragment 添加下面代碼用來處理傳過來的數據:

   /**
     * 接收解析后傳過來的數據
     */
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Object model = (Object) msg.obj;
            showPictures(model);
        }
    };

這樣就能后完美的解決這個問題了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM