【问题标题】:is there any other solution with CalledFromWrongThreadException? [duplicate]CalledFromWrongThreadException 还有其他解决方案吗? [复制]
【发布时间】:2015-04-28 13:52:58
【问题描述】:

我正在尝试使用 JSON 和 php 从 phpMyAdmin 获取数据。我正在使用安卓工作室。我尝试使用进度对话框,然后窗口泄漏(已经使用 p.Dialog.dismiss())。之后,我删除了进度对话框,然后出现新的异常。有没有其他方法可以解决这个问题?

这是我的日志。

 java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:299)
            at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
            at java.util.concurrent.FutureTask.run(FutureTask.java:239)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:838)
     Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5351)
            at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:970)
            at android.view.View.requestLayout(View.java:15722)
            at android.view.View.requestLayout(View.java:15722)
            at android.view.View.requestLayout(View.java:15722)
            at android.view.View.requestLayout(View.java:15722)
            at android.view.View.requestLayout(View.java:15722)
            at android.view.View.requestLayout(View.java:15722)
            at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:318)
            at android.view.View.requestLayout(View.java:15722)
            at android.widget.TextView.checkForRelayout(TextView.java:6605)
            at android.widget.TextView.setText(TextView.java:3804)
            at android.widget.TextView.setText(TextView.java:3662)
            at android.widget.TextView.setText(TextView.java:3637)
            at com.example.ayim.madoc.docProfile$DocProfile.doInBackground(docProfile.java:113)
            at com.example.ayim.madoc.docProfile$DocProfile.doInBackground(docProfile.java:67)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask.run(FutureTask.java:234)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:838) 

这是我写的代码。

package com.example.ayim.madoc;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;


public class docProfile extends ActionBarActivity {

    TextView nameDoc;
    TextView iddoc;
    TextView icdoc;
    TextView adddoc;
    TextView notel;

    private ProgressDialog pDialog;

    //JSONArray docprofile = null;

    JSONParser jsonParser = new JSONParser();

    private static final String LOGIN_URL = "http://104.223.3.210/madoc/docprofile.php";

    //JSON element ids from repsonse of php script:
    private static final String TAG_SUCCESS = "success";
    private static final String TAG_MESSAGE = "message";
    private static final String TAG_DOCTOR = "doctor";
    private static final String TAG_ID = "id";
    private static final String TAG_NAME = "name";
    private static final String TAG_IC = "ic";
    private static final String TAG_ADDRESS = "address";
    private static final String TAG_NOTEL = "notel";
    //String iddoctor;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_doc_profile);


       // Intent i = getIntent();

        //iddoctor = i.getStringExtra("idDoc");

        new DocProfile().execute();

        //nameDoc = (TextView) findViewById(R.id.docId);
        //nameDoc.setText(getIntent().getExtras().getString("idDoc"));


    }


    class DocProfile extends AsyncTask<String, String, String> {


/*
        @Override
        protected void onPreExecute() {

            super.onPreExecute();
            pDialog = new ProgressDialog(docProfile.this);
            pDialog.setMessage("Loading Profile. Please wait....");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }
*/

        @Override
        protected String doInBackground(String... params) {


            String idd = getIntent().getExtras().getString("idDoc");

                    int success;
                    try {

                        List<NameValuePair> param = new ArrayList<NameValuePair>();
                        param.add(new BasicNameValuePair("id",idd));

                        JSONObject json = jsonParser.makeHttpRequest(LOGIN_URL, "GET", param);

                        Log.d("Doctor Profile", json.toString());

                        success = json.getInt(TAG_SUCCESS);

                        if (success == 1) {

                            JSONArray docProfile = json.getJSONArray(TAG_DOCTOR);

                            JSONObject docProf = docProfile.getJSONObject(0);

                            nameDoc = (TextView) findViewById(R.id.name);
                            iddoc = (TextView) findViewById(R.id.docId);
                            icdoc = (TextView) findViewById(R.id.icdoctor);
                            adddoc = (TextView) findViewById(R.id.addressdoc);
                            notel = (TextView) findViewById(R.id.noteldoc);

                            nameDoc.setText(docProf.getString("name"));
                            iddoc.setText(docProf.getString("id"));
                            icdoc.setText(docProf.getString("ic"));
                            adddoc.setText(docProf.getString("address"));
                            notel.setText(docProf.getString("noTel"));

                        } else {
                            //no doctor
                        }

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }




            return null;
        }

        protected void onPostExecute(String file_url) {
            // dismiss the dialog once product deleted
            pDialog.dismiss();
            //if (file_url != null){
              //  Toast.makeText(docProfile.this, file_url, Toast.LENGTH_LONG).show();
           // }

        }


    }
}

【问题讨论】:

标签: java android multithreading android-asynctask


【解决方案1】:

该错误清楚地告诉您,您无法在主线程之外访问您的视图层次结构。

原因:android.view.ViewRootImpl$CalledFromWrongThreadException: 只有创建视图层次结构的原始线程才能触及其 意见。

由于您使用的是 AsyncTask,因此您最好在 onPostExecute 中更新您的 UI 元素。此方法将在主线程上运行。您可以将 docProf 传递给 onPostExecute 并在那里进行更改。

protected void onPostExecute(String file_url) {
    nameDoc = (TextView) findViewById(R.id.name);
    iddoc = (TextView) findViewById(R.id.docId);
    icdoc = (TextView) findViewById(R.id.icdoctor);
    adddoc = (TextView) findViewById(R.id.addressdoc);
    notel = (TextView) findViewById(R.id.noteldoc);

    nameDoc.setText(docProf.getString("name"));
    iddoc.setText(docProf.getString("id"));
    icdoc.setText(docProf.getString("ic"));
    adddoc.setText(docProf.getString("address"));
    notel.setText(docProf.getString("noTel"));

    pDialog.dismiss();
}

要将数据发送到 onPostExecute,您需要进行三处更改:

1:

class DocProfile extends AsyncTask<String, String, String> {

变成……

class DocProfile extends AsyncTask<String, String, JSONObject> {

2.

if (success == 1) {

变成……

if (success == 1) return docProf;

3.

protected void onPostExecute(String file_url) {

变成……

protected void onPostExecute(JSONObject docProf) {

您现在可以在 onPostExecute 中使用 docProf。

或者,此块中的所有内容:

if (success == 1) {

... 需要在 UI 线程上运行。

例子:

(new Handler(Looper.getMainLooper()).post(new Runnable() {
    public void run() {
        nameDoc = (TextView) findViewById(R.id.name);
        iddoc = (TextView) findViewById(R.id.docId);
        icdoc = (TextView) findViewById(R.id.icdoctor);
        adddoc = (TextView) findViewById(R.id.addressdoc);
        notel = (TextView) findViewById(R.id.noteldoc);

        nameDoc.setText(docProf.getString("name"));
        iddoc.setText(docProf.getString("id"));
        icdoc.setText(docProf.getString("ic"));
        adddoc.setText(docProf.getString("address"));
        notel.setText(docProf.getString("noTel"));
    }
});

【讨论】:

  • 如何将 docProf 传递给 onPostExecute?
  • 对不起..我还是新手..
  • 查看我的更新答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 2012-04-28
  • 2017-04-27
相关资源
最近更新 更多