【问题标题】:Android Studio error: "Method getText() must be called from the UI Thread, currently inferred thread is workerAndroid Studio 报错:“必须从 UI 线程调用方法 getText(),当前推断线程为 worker
【发布时间】:2015-12-10 15:55:42
【问题描述】:

我正在 android studio 中创建一个 CRUD 操作,但我不断收到错误。错误是当我检查 LogCat 时,这就是他们向我展示的内容

第 156-158 行
1907-1931/com.example.casquejo.loginadmin E/AndroidRuntime:致命 例外:异步任务 #2 进程:com.example.casquejo.loginadmin,PID:1907 java.lang.RuntimeException:执行时发生错误 做背景() 引起:java.lang.NullPointerException atcom.example.casquejo.loginadmin.NewProductActivity$CreateNewProduct.doInBackground(NewProductActivity.java:85) 在 com.example.casquejo.loginadmin.NewProductActivity$CreateNewProduct.doInBackground(NewProductActivity.java:58) atcom.example.casquejo.loginadmin.NewProductActivity$CreateNewProduct.onPreExecute(NewProductActivity.java:67) atcom.example.casquejo.loginadmin.NewProductActivity$1.onClick(NewProductActivity.java:53)

有人可以帮我解决这个问题,或者有人可以告诉我如何解决这个问题`下面是我的java类的代码EditProductActivity.class

       package com.example.casquejo.loginadmin;

        import java.util.ArrayList;
        import java.util.List;
        import org.apache.http.NameValuePair;
        import org.apache.http.message.BasicNameValuePair;
        import org.json.JSONException;
        import org.json.JSONObject;
        import android.app.Activity;
        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.Button;
        import android.widget.EditText;

        /**
        * Created by Casquejo on 9/14/2015.
        */
        public class NewProductActivity extends Activity {
    private ProgressDialog pDialog;

    JSONParser jsonParser = new JSONParser();
    EditText inputName;
    EditText inputPrice;
    EditText inputDesc;

    private static String url_create_product = "http://10.0.2.2/android_connect/create_product.php";

    private static final String TAG_SUCCESS = "success";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.add_product);

        inputName = (EditText) findViewById(R.id.inputName);
        inputPrice = (EditText) findViewById(R.id.inputPrice);
        inputDesc = (EditText) findViewById(R.id.inputDesc);

        Button btnCreateProduct = (Button) findViewById(R.id.btnCreateProduct);
        btnCreateProduct.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                String name = inputName.getText().toString();
                String price = inputPrice.getText().toString();
                String description = inputDesc.getText().toString();
                new CreateNewProduct().execute(name, price,description);
            }
        });
    }

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

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(NewProductActivity.this);
            pDialog.setMessage("Creating Product..");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();

        }

        protected String doInBackground(String... args) {

            String name = args[0],
                    price = args[1],
                    description = args[2];

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("name", name));
            params.add(new BasicNameValuePair("price", price));
            params.add(new BasicNameValuePair("description", description));

            JSONObject json = jsonParser.makeHttpRequest(url_create_product,
                    "POST", params);

            Log.d("Create Response", json.toString());

            try {
                int success = json.getInt(TAG_SUCCESS);

                if (success == 1) {
                    Intent i = new Intent(getApplicationContext(), AllProductsActivity.class);
                    startActivity(i);
                    finish();
                }
                else {

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

            return null;
        }

        protected void onPostExecute(String file_url) {
            pDialog.dismiss();
        }

    }
}

【问题讨论】:

  • 我会非常小心这段代码,你正在调用 findViewByID(...) 以从后台线程获取对 UI 元素的引用,该线程在 AsyncTask 中的 UI 线程上运行可运行对象(这本身不会感觉!)并且您没有防御性地使用任何 UI 小部件,这会使您面临空指针异常的风险。例如,我会将 txtName = (EditText) findViewById(R.id.inputName); 和 co 移至 onCreate() 方法

标签: java android multithreading android-asynctask


【解决方案1】:

ide指的是

  String name = txtName.getText().toString();
  String price = txtPrice.getText().toString();
  String description = txtDesc.getText().toString();

读取值应该不是问题,但为了消除此警告/错误,您可以将其移至onClick 并通过execute() 传递值。例如

btnSave.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View arg0) {
        String name = txtName.getText().toString();
        String price = txtPrice.getText().toString();
        String description = txtDesc.getText().toString();
        new SaveProductDetails().execute(name, price, description);
    }
});

doInBackground 被调用时,你可以通过前面的参数String... args 读取那些bac。可变参数的三个点构造保持不变,可变参数可以像数组一样访问,使用[] 表示法。在示例的情况下,

args[0] 包含name 的值,args[1] 包含price 的值,args[2] 包含description 的值。

【讨论】:

  • 非常感谢!谢谢大家的帮助我现在明白了我真的不能在doInBackground中使用它谢谢。
  • 你还有问题吗?
  • 先生,我已经按照您在回答中的建议进行了操作,但是当我检查 logcat 时我仍然遇到问题,错误是 onClick 以及 String...args 你能帮我解决吗?
  • 强制关闭错误,我现在可以运行应用程序,但是当我检查 Logcat 时转到添加部分或编辑部分时,这是错误。在 com.example.casquejo.loginadmin.NewProductActivity$CreateNewProduct.onPreExecute(NewProductActivity.java:67)
  • 我得到的错误是强制关闭,我可以运行整个应用程序,但我要添加或编辑部分应用程序正在强制关闭,但我输入的数据正在输入在数据库中。当我检查 LogCat 时,我发现了一些错误。 _ 我不知道如何在这里放图片,所以我不知道如何向您展示我的错误。_
【解决方案2】:

您从AsyncTask 产生的后台线程调用getText()

首先获取文本,然后调用您的异步任务。这是一个例子

new SaveProductDetails()
    .execute(txtName.getText().toString(), 
        txtPrice.getText().toString(), 
        txtDesc.getText().toString());

SaveProductDetailsdoInBackground方法内部:

String name = args[0],
       price = args[1],
       description = args[2];

【讨论】:

  • 非常感谢!谢谢大家的帮助我现在明白了我真的不能在doInBackground中使用它谢谢。
【解决方案3】:

在异步任务中,doInBackground(...) 方法在后台(非 UI)线程中运行。正如您在给出的错误中看到的那样,您不能与后台线程中的 UI 元素进行交互。

您可以按照其他答案之一的建议将参数传递到后台线程,或者您可以修改您的 asynctask,以便在 UI 上执行的 onPreExecute() 方法中读取 UI 字符串值线程(就像onPostExecute() 方法一样)。

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

private String name, price, description;

@Override
protected void onPreExecute() {
    super.onPreExecute();
    pDialog = new ProgressDialog(EditProductActivity.this);
    pDialog.setMessage("Saving product ...");
    pDialog.setIndeterminate(false);
    pDialog.setCancelable(true);
    pDialog.show();

    name = txtName.getText().toString();
    price = txtPrice.getText().toString();
    description = txtDesc.getText().toString();
}

protected String doInBackground(String... args) {
    //... Use as you would before

我建议您查看一篇博文,例如 this,以了解更多关于 AsyncTasks、它们如何工作、如何使用它们的信息,包括诸如在哪个线程上运行的方法等详细信息。

【讨论】:

  • 非常感谢!谢谢大家的帮助我现在明白了我真的不能在doInBackground中使用它谢谢。
  • 如果其中一个答案对您有所帮助,请不要忘记用答案左侧的箭头进行投票,并将其中一个标记为已接受且正确,以帮助其他人将来找到问题:)
  • 该死!哈哈,所有的答案都对我有帮助,我想给所有答案投票并接受。但对于未来的读者来说,所有的答案都是正确的,这些人真的帮了我很多:)
【解决方案4】:

您可以阅读此Using Variables on UI Thread from Worker Thread
在您的问题中,您正在尝试从后台线程访问 TextView 的文本。 为了保持一致,您不应该这样做,因为它们可能是主线程(UI线程同时设置TextView)。为了避免这样的风景,你可以这样:

class SaveProductDetails extends AsyncTask<String, String, String>{
      //create constructor and pass values of text view in it
      String textViewValue1;
      public SaveProductDetails (String textViewValue1 ){
           this.textViewValue1=textViewValue1
      }

     //other code below
} 

【讨论】:

    【解决方案5】:

    您不需要将值传递给执行方法。 将名称、价格和描述变量设置为全局变量。 要从按钮上的 EditTest 获取值,请单击下面的代码:

    每次需要点击按钮获取JSON数据。

    btnSave.setOnClickListener(new View.OnClickListener() {
    
        @Override
        public void onClick(View arg0) {
            name = txtName.getText().toString();
            price = txtPrice.getText().toString();
            description = txtDesc.getText().toString();
            new CreateNewProduct().execute();
        }
    });
    

    现在,无论您输入什么,名称、价格和描述都具有其价值。

    现在您的 CreateNewProduct 类看起来像这样:

    class CreateNewProduct extends AsyncTask<String, String, String> {
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(NewProductActivity.this);
            pDialog.setMessage("Creating Product..");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
    
        }
    
        protected String doInBackground(String... args) {
    
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("name", name));
            params.add(new BasicNameValuePair("price", price));
            params.add(new BasicNameValuePair("description", description));
    
            JSONObject json = jsonParser.makeHttpRequest(url_create_product,
                    "POST", params);
    
            Log.d("Create Response", json.toString());
    
            try {
                int success = json.getInt(TAG_SUCCESS);
    
                if (success == 1) {
                    Intent i = new Intent(getApplicationContext(), AllProductsActivity.class);
                    startActivity(i);
                    finish();
                }
                else {
    
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
        protected void onPostExecute(String file_url) {
            pDialog.dismiss();
        }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-05
      • 1970-01-01
      相关资源
      最近更新 更多