Android 在 AsyncTask 中崩溃

Android crash in AsyncTask

当我 运行 我的项目和 activity 的 运行 AsyncTask 显示项目的所有内容时,APP 崩溃显示以下错误消息:

06-17 20:56:52.856      418-428/? E/art﹕ Failed sending reply to debugger: Broken pipe
06-17 20:57:07.391      418-767/com.example.user.project_test E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #3
    Process: com.example.user.project_test, PID: 418
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask.done(AsyncTask.java:304)
            at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
            at java.util.concurrent.FutureTask.run(FutureTask.java:242)
            at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
     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:6357)
            at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:909)
            at android.view.ViewGroup.invalidateChild(ViewGroup.java:4690)
            at android.view.View.invalidateInternal(View.java:11801)
            at android.view.View.invalidate(View.java:11765)
            at android.view.View.invalidate(View.java:11749)
            at android.widget.TextView.checkForRelayout(TextView.java:6858)
            at android.widget.TextView.setText(TextView.java:4057)
            at android.widget.TextView.setText(TextView.java:3915)
            at android.widget.TextView.setText(TextView.java:3890)
            at com.example.user.project.itemActivity$getitem.doInBackground(itemActivity.java:132)
            at com.example.user.project.itemActivity$getitem.doInBackground(itemActivity.java:84)
            at android.os.AsyncTask.call(AsyncTask.java:292)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
06-17 20:57:07.612      418-418/com.example.user.project_test E/WindowManager﹕ android.view.WindowLeaked: Activity com.example.user.project.itemActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{19feb64d V.E..... R......D 0,0-1026,348} that was originally added here
            at android.view.ViewRootImpl.<init>(ViewRootImpl.java:363)
            at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:271)
            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
            at android.app.Dialog.show(Dialog.java:298)
            at com.example.user.project.itemActivity$getitem.onPreExecute(itemActivity.java:96)
            at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:591)
            at android.os.AsyncTask.execute(AsyncTask.java:539)
            at com.example.user.project.itemActivity.onCreate(itemActivity.java:71)
            at android.app.Activity.performCreate(Activity.java:5990)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access0(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.description.invoke(Native description)
            at java.lang.reflect.description.invoke(description.java:372)
            at com.android.internal.os.ZygoteInit$descriptionAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

我把我当前的代码放在这里

ItemActivity.java(这是在 AsyncTask 中崩溃的 class:

public class ItemActivity extends AppCompatActivity {

    private static final String TAG_SUCCESS = "success";
    private static final String TAG_ITEM = "item";
    private static final String TAG_ITEM_NAME = "name";
    private static final String TAG_ITEM_description = "item";

    Integer item_id;
    String name;
    String username;
    String item;
    TextView itemname;
    TextView itemitem;
    ProgressDialog pDialog;
    JSONParser jParser;
    RecyclerView recycler;
    ActionBar actionBar;

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

        Intent i = getIntent();
        if (i.hasExtra("item_id")) {
            Bundle bd = getIntent().getExtras();
            /*if ((!bd.getString("name").equals(null) || bd.getString("name").trim().length() > 0) && (!bd.getString("username").equals(null) || bd.getString("username").trim().length() > 0) && (!bd.getString("description").equals(null) || bd.getString("description").trim().length() > 0)) {
                name = bd.getString("name");
                username = bd.getString("username");
                description = bd.getString("description");
            }*/
            item_id = bd.getInt("item_id");
        }

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        actionBar = getSupportActionBar();
        actionBar.setTitle(R.string.app_name);

        itemname = (TextView) findViewById(R.id.itemName);
        itemdescription = (TextView) findViewById(R.id.itemDescription);

        new getitem().execute();
        /*recycler = (RecyclerView) findViewById(R.id.recycler);
        recycler.setHasFixedSize(true);

        LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recycler.setLayoutManager(layoutManager);*/

    }

    /**
     * Background Async Task to Get complete item details
     */
    class getitem extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Dialog
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            if (pDialog != null) {
                pDialog = null;
            }
            pDialog = new ProgressDialog(itemActivity.this);
            pDialog.setMessage(getResources().getString(R.string.loadingitem));
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
            pDialog.show();
        }

        /**
         * Getting item details in background thread
         */
        protected String doInBackground(String... params) {

            // updating UI from Background Thread

            // Check for success tag
            int success;
            try {
                // Building Parameters
                List<NameValuePair> myParameters = new ArrayList<NameValuePair>();
                myParameters.add(new BasicNameValuePair("item_id", Integer.toString(item_id)));

                // getting item details by making HTTP request
                // Note that item details url will use GET request
                jParser = new JSONParser();
                JSONObject json = jParser.makeHttpRequest(AppConfig.URL_GET_item, "GET", myParameters);

                // check your log for json response
                Log.d("Single item Details", json.toString());

                // json success tag
                success = json.getInt(TAG_SUCCESS);
                if (success == 1) {
                    // successfully received item details
                    JSONArray itemObj = json.getJSONArray(TAG_item); // JSON Array

                    // get first item object from JSON Array
                    JSONObject item = itemObj.getJSONObject(0);

                    // item with this pid found
                    // Edit Text
                    itemname.setText(item.getString(TAG_item_NAME));
                    itemdescription.setText(item.getString(TAG_item_description));
                } else {
                    // item with pid not found
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog
         * *
         */
        protected void onPostExecute(String file_url) {
            // dismiss the dialog once got all details
            pDialog.dismiss();
        }
    }

    /*itemname=(TextView)

    findViewById(R.id.itemName);

    itemdescription=(TextView)

    findViewById(R.id.itemdescription);*/

    //itemname.setText(name);
    //itemdescription.setText(description);

}

activity_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="@bool/fitsSystemWindows">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/status_bar_height"
            android:background="?colorPrimary" />

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/status_bar_height"
            android:background="?colorPrimaryDark" />

    </LinearLayout>

    <FrameLayout
        android:id="@+id/flma"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/status_bar_height">

        <TextView
            android:id="@+id/itemName"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|top"
            android:layout_marginTop="80dp"
            android:gravity="center"
            android:textAllCaps="true"
            android:textSize="25dp"
            android:textStyle="bold" />

        <ImageView
            android:id="@+id/itemPhoto"
            android:layout_width="fill_parent"
            android:layout_height="300dp"
            android:layout_gravity="center"
            android:background="#000"
            android:src="@drawable/header" />

        <TextView
            android:id="@+id/itemdescription"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|bottom"
            android:layout_marginBottom="50dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="Large Text"
            android:textAppearance="?android:attr/textAppearanceLarge" />

    </FrameLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="@bool/fitsSystemWindows"
        app:headerLayout="@layout/navigation_drawer_header"
        app:menu="@menu/navigation_drawer_menu"
        app:theme="@style/NavigationViewTheme" />

</android.support.v4.widget.DrawerLayout>

我正在搜索,我发现检查进度对话框是否不为 null 将其设置为 null 问题可以解决,但对我不起作用。

有谁知道我的 class 中是否有误?

谢谢!!

解决方案:

感谢 Itzik Samara 和 ligi 对问题的帮助和解释,我解决了这个问题,删除了 Itzik Samara 指示的行并在 onPostExecute 中添加了以下代码:

protected void onPostExecute(String file_url) {
            // dismiss the dialog once got all details

            try {
                itemname.setText(item.getString(TAG_item_NAME));
            } catch (JSONException e) {
                e.printStackTrace();
            }
            try {
                itemdescription.setText(item.getString(TAG_item_description));
            } catch (JSONException e) {
                e.printStackTrace();
            }
            pDialog.dismiss();
        }

你不能触及后台线程中的 UI 元素(比如 setText) UI 线程)并阅读有关 android 线程

你的问题是那两行:

itemname.setText(item.getString(TAG_ITEM_NAME));
itemdescription.setText(item.getString(TAG_ITEM_DESCRIPTION));

2 个选择:

  1. 将数据发送到 onPostExecute 并从那里更新 EditText
  2. 使用RunOnUiThread并更新里面的2个EditText

尝试将此添加到您的 doInBackground()

runOnUiThread(new Runnable() {
            @Override
            public void run() {
                itemname.setText(item.getString(TAG_item_NAME));
                itemdescription.setText(item.getString(TAG_item_description));
            }
});

或者把这两行放在onPostExecute()

itemname.setText(item.getString(TAG_item_NAME));
itemdescription.setText(item.getString(TAG_item_description));

这是你的全部 Class

public class itemActivity extends AppCompatActivity {

private static final String TAG_SUCCESS = "success";
private static final String TAG_item = "item";
private static final String TAG_item_NAME = "name";
private static final String TAG_item_description = "description";

Integer item_id;
String name;
String username;
String description;
TextView itemname;
TextView itemdescription;
ProgressDialog pDialog;
JSONParser jParser;
RecyclerView recycler;
ActionBar actionBar;

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

    Intent i = getIntent();
    if (i.hasExtra("item_id")) {
        Bundle bd = getIntent().getExtras();
        /*if ((!bd.getString("name").equals(null) || bd.getString("name").trim().length() > 0) && (!bd.getString("username").equals(null) || bd.getString("username").trim().length() > 0) && (!bd.getString("description").equals(null) || bd.getString("description").trim().length() > 0)) {
            name = bd.getString("name");
            username = bd.getString("username");
            description = bd.getString("description");
        }*/
        item_id = bd.getInt("item_id");
    }

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    actionBar = getSupportActionBar();
    actionBar.setTitle(R.string.app_name);

    itemname = (TextView) findViewById(R.id.itemName);
    itemdescription = (TextView) findViewById(R.id.itemdescription);

    new getitem().execute();
    /*recycler = (RecyclerView) findViewById(R.id.recycler);
    recycler.setHasFixedSize(true);

    LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    recycler.setLayoutManager(layoutManager);*/

}

/**
 * Background Async Task to Get complete item details
 */
class getitem extends AsyncTask<String, String, String> {

    /**
     * Before starting background thread Show Progress Dialog
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        if (pDialog != null) {
            pDialog = null;
        }
        pDialog = new ProgressDialog(itemActivity.this);
        pDialog.setMessage(getResources().getString(R.string.loadingitem));
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(false);
        pDialog.show();
    }

    /**
     * Getting item details in background thread
     */
    protected String doInBackground(String... params) {

        // updating UI from Background Thread

        // Check for success tag
        int success;
        try {
            // Building Parameters
            List<NameValuePair> myParameters = new ArrayList<NameValuePair>();
            myParameters.add(new BasicNameValuePair("item_id", Integer.toString(item_id)));

            // getting item details by making HTTP request
            // Note that item details url will use GET request
            jParser = new JSONParser();
            JSONObject json = jParser.makeHttpRequest(AppConfig.URL_GET_item, "GET", myParameters);

            // check your log for json response
            Log.d("Single item Details", json.toString());

            // json success tag
            success = json.getInt(TAG_SUCCESS);
            if (success == 1) {
                // successfully received item details
                JSONArray itemObj = json.getJSONArray(TAG_item); // JSON Array

                // get first item object from JSON Array
                JSONObject item = itemObj.getJSONObject(0);

                // item with this pid found
                // Edit Text
                runOnUiThread(new Runnable() {
                @Override
                 public void run() {
                   itemname.setText(item.getString(TAG_item_NAME));
                   itemdescription.setText(item.getString(TAG_item_description));
                 }
                });
            } else {
                // item with pid not found
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * After completing background task Dismiss the progress dialog
     * *
     */
    protected void onPostExecute(String file_url) {
        // dismiss the dialog once got all details
        pDialog.dismiss();
    }
}

}