我有一个具有登录功能的Android应用程序,登录框中有一个TextView
,用于在尝试登录时向用户显示消息(即错误的名称,错误的传递等等)。
我有两种方法,第一种方法检查字段是否已填满,如果已填充,则将应用程序重定向到第二种方法,该方法将检查来自本地服务器的用户/传递。 问题是在第二种方法中重置文本时,因为当我在第一种方法中设置文本时一切正常,但在第二种方法中更改它时它没有改变,我可以在第一种方法中将其设置为百万次方法和一切顺利,另一件事是当我第一次从第二种方法设置文本时它完美地工作。
提示1 :第一种方法是onClick
的{{1}}方法。
提示2 :在logcat中打印的日志被装载了数百万次,因此验证了while条件
OnClickListener
第一种方法:
public class Login extends Activity {
public EditText user, pw;
public TextView errorMessage;
private static String response = null;
private static String data;
第二种方法:
public void onClick(View v) {
if (v == login) {
String userName = Login.this.user.getText().toString();
String Password = Login.this.pw.getText().toString();
if (userName.equals(null_string)
|| Password.equals(null_string)) {
errorMessage.setText(R.string.request);
} else {
protocol = protocol_login;
boolean status = false;
try {
status = checkLogin(userName, Password);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
if (status) {
Intent intent = new Intent(v.getContext(),
MainPage.class);
go(intent);
} else {
errorMessage.setText(R.string.login_error);
}
}
}
}
答案 0 :(得分:3)
你的问题在于,在第二种方法中,你试图在实际成为第二个线程时更新GUI。
你可以使用runOnUIThread方法
Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
errorMessage.setText(R.string.waiting);
}
});
while (response == null) {
System.out.println("waiting");
}
如果文本没有改变,你也不应该在while循环中设置文本,这样你就不会使用不必要的资源。
答案 1 :(得分:1)
我不确定究竟是什么导致了您的问题(您正在某处阻止UI线程),但有更好的方法从服务器获取响应。您基本上是在同步检查异步响应(如下所示),因为您一直在轮询response
是否为空。
Android有一个名为AsyncTask的有用类。你给一个AsyncTask在后台线程上做了一些工作(ConnectToServer(..)
做了什么),当它完成时,调用AsyncTask上的另一个方法(称为onPostExecute(..)
)。这对您的方法的好处是它为您处理所有线程,并且不进行轮询。您还可以使用方法onPreExecute()
设置等待文本。
N.B。同步检查异步响应
我的意思是,响应可以随时(异步)返回,但您可以在任何时候(同步)检查它。这会浪费CPU上的宝贵资源 - 你应该在完成后得到 告诉 的响应,而不是 问 是否。
答案 2 :(得分:1)
首先,这两个字符串变量全局声明:
String userName,Password
试试这个简单的Asyntask方法:
private class SetDataOfWebService extends AsyncTask<Void, Void,Boolean> {
ProgressDialog pDialog;
boolean success = false;
ConnectivityManager connectivity;
@Override
protected void onPreExecute() {
pDialog = new ProgressDialog(MailSettings.this);
pDialog.setMessage("Please Wait..");
pDialog.show();
}
@Override
protected Boolean doInBackground(Void... params) {
if (isNetworkAvailable()) {
success = true;
if (userName.length()>0 || Password.length()>0) {
status = checkLogin(userName, Password);
}
else
{
errorMessage.setText(R.string.request);
}
} else {
success = false;
}
return success;
}
@Override
protected void onPostExecute(Boolean result) {
if (pDialog != null && pDialog.isShowing())
pDialog.dismiss();
if (result) {
if (status) {
Intent intent = new Intent(v.getContext(),
MainPage.class);
go(intent);
} else {
errorMessage.setText(R.string.login_error);
}
} else {
return;
}
}
public boolean isNetworkAvailable() {
connectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
Log.i("Class", info[i].getState().toString());
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
}
return false;
}
}
////Calling This Function On Button CLick Like This
userName = Login.this.user.getText().toString();
Password = Login.this.pw.getText().toString();
new SetDataOfWebService().execute();