我需要从我的服务器获取一些数据才能让我的应用运行起来。为了做到这一点,我将使用POST。据我所知,我必须在一个不能成为主线程的线程中请求数据。我发现有点难以将我正在接收的数据放在UI线程中定义的变量中。所以,我的问题是,这是最好的方法吗? 设置一个变量的值是否正确,例如,在我的主要活动中,使用在AsyncTask内部调用的setter?或者这个选项可能更好?
Thread nt = new Thread(){
@Override
public void run(){
try{
//get data with POST and then something like main.setValue(data);
}catch(Exception e){
e.printStackTrace();
}
}
};
nt.start();
我已经读过,我可能会使用Interfaces来存档,但这是一个我不太了解的概念。我想直接使用一个返回数据的方法,但据我所知,这是不可能的。 Thabks你的时间!
编辑:NoChinDeluxe的新代码回答:
public class LoginHandler {
public static class Login extends AsyncTask<String, String, Integer> {
LoginCallback listener;
@Override
protected Integer doInBackground(String... params) {
URL url;
postDataParams.put("name", params[0]);
HashMap<String, String> postDataParams = new HashMap<String, String>();
postDataParams.put("password", params[1]);
try {
url = new URL("http://mashiron.xyz/_03z/gmpia/proc.php");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(HttpHandler.getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
System.out.println("Respuesta: "+conn.getResponseCode());
return conn.getResponseCode();
} catch (Exception e) {
e.printStackTrace();
return 404;
}
}
protected void onPostExecute(int result){
System.out.println("Respuesta 2: "+result);
listener.onResultReceived(result);
}
}
public interface LoginCallback {
void onResultReceived(int result);
}
}
编辑:为NoChinDeluxe添加了例外:
03-24 17:38:09.072 13312-13312 / com.pitazzo.geomoments E / AndroidRuntime:致命异常:主要 过程:com.pitazzo.geomoments,PID:13312 java.lang.NullPointerException:尝试调用接口方法&#39; void com.pitazzo.geomoments.Handlers.LoginHandler $ LoginCallback.onResultReceived(int)&#39;在null对象引用上 在com.pitazzo.geomoments.Handlers.LoginHandler $ Login.onPostExecute(LoginHandler.java:65) 在com.pitazzo.geomoments.Handlers.LoginHandler $ Login.onPostExecute(LoginHandler.java:17) 在android.os.AsyncTask.finish(AsyncTask.java:636) 在android.os.AsyncTask.access $ 500(AsyncTask.java:177) 在android.os.AsyncTask $ InternalHandler.handleMessage(AsyncTask.java:653) 在android.os.Handler.dispatchMessage(Handler.java:102) 在android.os.Looper.loop(Looper.java:135) 在android.app.ActivityThread.main(ActivityThread.java:5300) at java.lang.reflect.Method.invoke(Native Method) 在java.lang.reflect.Method.invoke(Method.java:372) 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:904) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
编辑:NoChainDeluxe的更多代码
public class LoginActivity extends AppCompatActivity implements LoginHandler.LoginCallback{
EditText name;
EditText password;
Button login;
int code;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_activity);
/*
if(logueado){
}
*/
name = (EditText) findViewById(R.id.loginuser);
password = (EditText) findViewById(R.id.loginpassword);
login = (Button) findViewById(R.id.loginlogin);
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String params[] = {name.getText().toString(), password.getText().toString()};
System.out.println("Params: "+params.toString());
new LoginHandler.Login().execute(params);
System.out.println("Respuesta 4: "+code);
if(code == 200){
Toast toast1 =
Toast.makeText(getApplicationContext(),
"Iniciado sesión", Toast.LENGTH_SHORT);
toast1.show();
}else{
Toast toast1 =
Toast.makeText(getApplicationContext(),
"Nombre de usuario y/o contraseña incorrectos: "+code, Toast.LENGTH_SHORT);
toast1.show();
}
}
});
}
public void onResultReceived(int resultado) {
code = resultado;
System.out.println("Respuesta 3: "+code);
}
}
答案 0 :(得分:4)
实现此目标的最佳方法是使用HttpURLConnection
在AsyncTask
内进行网络调用,然后通过回调将结果传回给您的调用活动。这里有一些代码可以帮助您入门:
您应该了解的第一件事是如何正确使用AsyncTask
的回调。以下是定义回调接口的示例AsyncTask
:
import android.os.AsyncTask;
public class TestTask extends AsyncTask<String, Void, String> {
TestTaskCallback listener;
public TestTask(TestTaskCallback listener) {
this.listener = listener;
}
protected String doInBackground(String... args) {
String input = args[0];
String output = "simulated return value";
return output;
}
protected void onPostExecute(String result) {
listener.onResultReceived(result);
}
public interface TestTaskCallback {
void onResultReceived(String result);
}
}
这样做的方法是,定义一个公共接口,然后在Activity中实现。这充当“监听器”,等待发送给它的任何数据。我们定义了接口TestTaskCallback
,因为我们要将数据从AsyncTask
发送到我们的调用活动。
然后在Activity中,我们需要实现这个接口,并在创建它时将对我们的实现的引用传递给任务。这样,当任务触发时,它知道将结果发送到何处,这将返回到我们的Activity。示例实现可能如下所示:
public class TestActivity extends AppCompatActivity implements TestTask.TestTaskCallback {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
new TestTask(this).execute("Some input");
}
public void onResultReceived(String result) {
Log.d("TEST TASK RESULT", result);
}
}
因此我们的Activity实现了我们在AsyncTask
中定义的接口,并注意到我们的AsyncTask
接受了对此实现的引用(通过构造函数传入)并在{ {1}}方法。这将允许您的结果发送到主UI线程,以便您可以适当地更新您的活动。
唯一剩下的就是实际进行网络通话。我建议使用onPostExecute()
。您可以将此代码放在HttpURLConnection
的{{1}}方法中。
我将向您展示我已设置的示例Web服务调用。这显示了如何进行Web服务调用以检索JSON响应。它看起来像这样:
doInBackground()
这几乎是你需要知道的,你要做的就是你要做的事情。我意识到这有很多信息可以立即引发你的注意,但是如果你花时间一点一点地完成它,你会发现它毕竟并不太难,实际上它是一个非常强大的工具,你'我会一直使用Android应用编程!
希望这会有所帮助。您可以随意为您尚未完全理解的任何部分提问:
答案 1 :(得分:1)
最好使用AsyncTask将数据传播到您的UI线程,只需使用onPostExecute()
在您的活动类中设置结果。
答案 2 :(得分:0)