doInBackground 不更新变量

doInBackground not updating variable

我正在开发一个基本的 android 应用程序,它使 POST 具有 HttpURLConnection。我想 return 来自我的网站的响应消息 API。

我的MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView mTextView = findViewById(R.id.textView);
        AsyncExample asyncExample = new AsyncExample();
        asyncExample.execute();
        mTextView.setText(asyncExample.getResponseMsg());
    }
}

我的AsyncExample.java

class AsyncExample extends AsyncTask<Void, Void, Void> {
    private HttpURLConnection con;
    private String responseMsg;

    protected void onPreExecute() {
        responseMsg = "empty message";
    }

    @Override
    protected Void doInBackground(Void... params) {
        String urlParameters = "param1=data1";

        byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8"));
        int postDataLength = postData.length;
        String request = "http://192.168.1.30:6262";
        URL url = null;
        try {
            url = new URL(request);
            con = (HttpURLConnection) url.openConnection();
            con.setDoOutput(true);
            con.setInstanceFollowRedirects(false);
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            con.setRequestProperty("charset", "utf-8");
            con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
            responseMsg = con.getResponseMessage();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String getResponseMsg() {
        return responseMsg;
    }
}

在 运行 应用程序之后,我在 TextView 中得到 empty message。为什么它没有更新我的 doInBackground?即使con.getResponseMessage()null,也要更新吗?

尝试这样做

主要活动

public class MainActivity extends AppCompatActivity {
TextView mTextView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mTextView = findViewById(R.id.textView);
    AsyncExample asyncExample = new AsyncExample(this,mTextView);
    asyncExample.execute();
  }
}

异步任务

    class AsyncExample extends AsyncTask<Void, Void, Void> {
    private HttpURLConnection con;
    private String responseMsg;
    private MainActivity mContext;
    TextView mTextView;

    public AsyncExample (MainActivity context, TextView textView) {
        mContext = context;
        mTextView = textView;
    } 

    protected void onPreExecute() {
        responseMsg = "empty message";
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected Void doInBackground(Void... params) {
        String urlParameters = "param1=data1";

        byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
        int postDataLength = postData.length;
        String request = "http://192.168.1.30:6262";
        URL url = null;
        try {
            url = new URL(request);
            con = (HttpURLConnection) url.openConnection();
            con.setDoOutput(true);
            con.setInstanceFollowRedirects(false);
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            con.setRequestProperty("charset", "utf-8");
            con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
            responseMsg = con.getResponseMessage();
            mContext.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mTextView.setText(responseMsg);
                }
            });
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String getResponseMsg() {
        return responseMsg;
    }
}

AsyncTask 有 3 个默认方法 1. 预执行 2.在后台做 3. 在 post 执行

post执行:

从 doinbackground 得到的响应在 post 执行中。 在这里我们可以处理结果。使用 runnable 方法更新文本视图 ui

onPostExecute() 方法重写为 return 文本。在 Main Activity 中创建一个方法来在完成异步任务的执行后更新 TextView。它变为空白,因为 Main Thread 没有暂停其执行和设置文本视图,但异步任务尚未完成执行,因此字符串为空。所以在设置文本视图之前等待异步任务完成。

String str_result= new RunInBackGround().execute().get();

Refer to this for more information.

您的 doInBackground 方法需要时间来执行。您正在立即呼叫 mTextView.setText(asyncExample.getResponseMsg());asynctask 尚未完成。你需要等到你的 doInBackground 完成然后调用 setText 你可以在 onPostExecute 方法中完成。

您可以通过多种方式进行。我会尝试向您推荐一种方法,该方法只需对现有代码进行微不足道的更改。

将 mTextView 声明为全局变量,覆盖 AsyncExample 中的 onPostExecute() 方法,并使用 doInBackground() 方法传递给它的值更新 onPostExecute() 方法中的 mTextView [此处,注意返回了 responseMsg在 doInBackground() 地面的末尾,它被 onPostExecute() 方法捕获为字符串值(结果)]。但是,我也认为重写您的 onPreExecute() 方法是个好主意。

为此,您的 MainActivity.java 应如下所示:

public class MainActivity extends AppCompatActivity {
TextView mTextView;    //declare mTextView outside the onCreate() method as a Global String variable.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.textView);
        AsyncExample asyncExample = new AsyncExample();
        asyncExample.execute();
    }
}

请将您的 asynctask 设为相同 activity 的 inner-class 并按如下方式编辑:

    class AsyncExample extends AsyncTask<Void, Void, Void> {
    private HttpURLConnection con;
    private String responseMsg;

    @Override           // Its a good practice to Override the onPreExecute() method.
    protected void onPreExecute() {
        responseMsg = "empty message";
    }

    @Override
    protected String doInBackground(String... params) {
        String urlParameters = "param1=data1";

        byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8"));
        int postDataLength = postData.length;
        String request = "http://192.168.1.30:6262";
        URL url = null;
        try {
            url = new URL(request);
            con = (HttpURLConnection) url.openConnection();
            con.setDoOutput(true);
            con.setInstanceFollowRedirects(false);
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            con.setRequestProperty("charset", "utf-8");
            con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
            responseMsg = con.getResponseMessage();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return responseMsg;    //return the value of responseMsg
    }

        @Override      //override onPostExecute() method
        protected void onPostExecute(String result) {    //receive the value to be set to mTextView which is returned by the doInBackground() method.
           mTextView.setText(result);
    }

}

问题是您的 AsyncTask 是异步执行的,而您试图立即检索值。您需要稍微不同地实现它。要么利用 AsyncTask 的 API,因为它会在 UI 线程上为您发布回调。您可以直接在 AsyncTask

中更新 TextView
class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> {

    @Override
    protected void onPreExecute() {
        myTextView.setText("progress started");
    }

    @Override
    protected String doInBackground(final Void... voids) {
        String s = amazingCallToBackend();
        return s;
    }

    @Override
    protected void onPostExecute(final String s) {
        myTextView.setText(s);
    }
}

或者,如果您只想要该值,则可以将回调传递给异步任务,它将向您传递该值,类似这样

interface Callback {
    void onValueReceived(String value);
    void onFailure();
}

class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> {

    private Callback callback;

    MyAwesomeAsyncTask(final Callback callback) {
        this.callback = callback;
    }

    @Override
    protected String doInBackground(final Void... voids) {
        String s = amazingCallToBackend();
        return s;
    }

    @Override
    protected void onPostExecute(final String s) {
        callback.onValueReceived(s);
    }
}

创建方法如下

Callback callback = new Callback() {
        @Override
        public void onValueReceived(final String value) {

        }

        @Override
        public void onFailure() {

        }
    };

new MyAwesomeAsyncTask(callback).execute();

但是,要小心,因为如果由于某种原因你的 activity/fragment 在你的 AsyncTask 完成之前是 gone/finished,这可能会导致内存泄漏。

快速 Google 搜索将告诉您有关 AsyncTask 内存泄漏的所有信息:)