英文:
Update global variable by using a interface
问题
我在我的MainActivity.java中有一个异步类:
class Register extends AsyncTask<String, String, JSONObject> {
JSONObject json;
@Override
protected JSONObject doInBackground(String[] args) {
String function = args[3];
String email = args[2];
String password = args[1];
String name = args[0];
ContentValues params = new ContentValues();
params.put("username", name);
params.put("password", password);
params.put("function", function);
if (email.length() > 0)
params.put("email", email);
String URL = "https://lamp.ms.wits.ac.za/home/s2090704/index.php";
new PhpHandler().makeHttpRequest(act, URL, params, new RequestHandler() {
@Override
public void processRequest(String response) throws JSONException {
json = new JSONObject(response);
System.out.println(json); // 输出 {response: "...", message: "..."}
}
});
System.out.println(json); // 输出 null
return json;
}
}
在doInBackground()方法中,PhpHandler使用OkHttp处理细节:
public class PhpHandler {
JSONObject json;
static String responseData = "";
public void makeHttpRequest(final Activity a, String url,
ContentValues params, final RequestHandler rh) {
// Making HTTP request
OkHttpClient client = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
for (String key : params.keySet()) {
builder.add(key, params.getAsString(key));
}
final Request request = new Request.Builder()
.url(url)
.post(builder.build())
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
responseData = Objects.requireNonNull(response.body()).string();
//System.out.println(responseData);
a.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
rh.processRequest(responseData);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
}
RequestHandler是一个在主线程上处理请求的接口:
package com.example.registration;
import org.json.JSONException;
public interface RequestHandler {
void processRequest(String response) throws JSONException;
}
现在,在我的异步类Register的doInBackground方法的processRequest方法外,json不会更新。我知道接口会使变量成为静态和最终的,是否有任何方法可以更新json的值?
英文:
I have a async class in my MainActivity.java
class Register extends AsyncTask<String, String, JSONObject> {
JSONObject json;
@Override
protected JSONObject doInBackground(String[] args) {
String function = args[3];
String email = args[2];
String password = args[1];
String name = args[0];
ContentValues params = new ContentValues();
params.put("username", name);
params.put("password", password);
params.put("function", function);
if (email.length() > 0)
params.put("email", email);
String URL = "https://lamp.ms.wits.ac.za/home/s2090704/index.php";
new PhpHandler().makeHttpRequest(act, URL, params, new RequestHandler() {
@Override
public void processRequest(String response) throws JSONException {
json = new JSONObject(response);
System.out.println(json); //outputs {response: " ...",message:"..."}
}
});
System.out.println(json); //outputs null
return json;
}
}
in doInBackground() PhpHandler processes details using OkHttp.
public class PhpHandler {
JSONObject json;
static String responseData = "";
public void makeHttpRequest(final Activity a, String url,
ContentValues params, final RequestHandler rh) {
// Making HTTP request
OkHttpClient client = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
for (String key : params.keySet()) {
builder.add(key, params.getAsString(key));
}
final Request request = new Request.Builder()
.url(url)
.post(builder.build())
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
responseData = Objects.requireNonNull(response.body()).string();
//System.out.println(responseData);
a.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
rh.processRequest(responseData);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
}
RequestHandler is an interface that processes request on the mainUiThread.
package com.example.registration;
import org.json.JSONException;
public interface RequestHandler{
void processRequest(String response) throws JSONException;
}
Now json doesn't update out of the processRequest method in doInBackground method of my async class Register.I know that interfaces make variables static and final is there any way to update the value of json?
答案1
得分: 0
processRequest
方法将在你从 doInBackground
返回 json
之后很长时间才会执行,因为 makeHttpRequest
执行异步的 HTTP 请求。
知道这一点后,你可能会想要重新设计这个类(没有必要在 AsyncTask
中包装已经是异步请求的部分),但如果你真的想要这样做,你将不得不在返回 json 之前等待请求完成(例如,使用 CountDownLatch)。
CountDownLatch latch = new CountDownLatch(1);
someField = null;
AtomicReference<String> someValue = new AtomicReference<>();
// 不要像这样启动新线程,我只是为了保持这个示例简单
new Thread() {
Thread.sleep(1000); // 等待 1 秒
someValue.set("abc"); // 注意,当使用 AtomicReference 时,你可以使用 `set` 方法而不是 `=` 运算符来赋值其值,可以将其保持为局部变量而不是类字段
latch.countDown(); // 将 latch 计数减一
}.run();
System.out.println(someValue.get()); // null - 因为赋值将会在一秒后发生
latch.await(); // 这将强制当前线程等待,直到 latch 计数达到零(初始值为 1,传递给构造函数)
System.out.println(someValue.get()); // "abc"
英文:
processRequest
method will be executed long after you return json
from doInBackground
, because makeHttpRequest
performs an asynchronous http request.
Knowing this, you will probably want to re-design this class (there is no need to wrap already asynchronous request in AsyncTask
), but if you really want to do it this way, you would have to wait for your request to complete before returning the json (for example, by using CountDownLatch).
CountDownLatch latch = new CountDownLatch(1);
someField = null;
AtomicReference<String> someValue = new AtomicReference<>();
// don't start new threads like this, im just trying to keep this example simple
new Thread() {
Thread.sleep(1000); // sleep for 1 second
someValue.set("abc"); // notice that because when using AtomicReference you assign it's value using `set` method instead of `=` operator, you can keep it as local variable instead of field class
latch.countDown(); // reduce latch count by one
}.run();
System.out.println(someValue.get()); // null - because the assignation will happen in one second
latch.await(); // this will force current thread to wait until the latch count reaches zero (initial was 1, passed to constructor)
System.out.println(someValue.get()); // "abc"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论