我有一个Android应用程序,其中有许多场景,其中请求和响应发生在服务器上。例如:login
,即authentication
。当用户输入username
和password
时,将根据服务器响应的凭据验证凭据。
但有时会发生的事情是,由于网络速度缓慢,响应来得很晚,而且Android会弹出一个强制关闭对话框,这非常令人尴尬。
我在想是否有办法隔离在某个单独的线程中点击服务器的代码,直到它得到我的响应。我可能会显示进度条而不是强制关闭。这是一个很好的解决方案吗?
示例代码:
//this code will be called when user presses Login button on UI
public void authenticate(View view) {
//the logic for authentication
if(authentication==true){
//go to home page
}
}
在上面的代码中,我如何分离认证逻辑,以便在响应延迟时不会发生强制关闭。
我还要感谢任何其他更好的方法来解决这种强制关闭的情况。
答案 0 :(得分:4)
不要包含任何需要花时间在主线程中执行的任务。你应该在不同的线程中进行httpCommunication。它将避免这种ANR。
什么文档说>> 在Android中,应用程序响应性由活动管理器和Window Manager系统服务监视。当Android检测到以下某种情况时,它将显示特定应用程序的ANR对话框: 在5秒内没有响应输入事件(例如按键,屏幕触摸) BroadcastReceiver尚未在10秒内完成执行
阅读专为Designing for responsiveness and to avoid ANR
创建的文档您也可以使用AsyncTask。
答案 1 :(得分:0)
您可以使用AsyncTask
或http://loopj.com/android-async-http/
同时在UI上显示进度对话框。提供一个回调函数,一旦收到服务器的响应就会调用它。
答案 2 :(得分:0)
使用以下示例代码执行login
过程。您可以使用AsyncTask
来执行登录过程。
LoginActivity
类,使用AsyncTask
。
Login
按钮,我executing
AsyncTask
。 ProgressDialog
ProgressDialog
并向用户显示状态消息班级代码:
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class LoginActivity extends Activity {
private Button login_Button = null;
private EditText userNameText = null;
private EditText passwordText = null;
private String uName = "";
private String pass = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_login);
login_Button = (Button) findViewById(R.id.cmdDoLogin);
userNameText = (EditText) findViewById(R.id.editTextUserName);
passwordText = (EditText) findViewById(R.id.editTextPassword);
login_Button.setOnClickListener(new OnClickListener() {
public void onClick(View paramView) {
uName = userNameText.getText().toString().trim();
pass = passwordText.getText().toString().trim();
if (uName.equals("") || pass.equals("")) {
Toast.makeText(LoginActivity.this,
"Fill both username and password fields",
Toast.LENGTH_SHORT).show();
} else {
new LoginActivity.DoLoginProcess().execute(); // calling the AsyncTask here
}
}
});
}
private class DoLoginProcess extends AsyncTask<Void, Void, Integer> {
ProgressDialog pd = null;
@Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(LoginActivity.this);
pd.setTitle("Logging In...");
pd.setMessage("Please wait...");
pd.setCancelable(false);
pd.show();
}
@Override
protected Integer doInBackground(Void... params) {
int loginStatus = 0 ; // treat this as loginStatus. 0 = login failed; 1=login success. You can return this value to onPostExecute function
//*********************************************
// do login process over internet here. Hope you already have the code to do the login process over internet.
//*********************************************
return loginStatus;
}
@Override
protected void onPostExecute(Integer status) {
super.onPostExecute(status);
pd.dismiss(); // dismiss the progress dialog
if (status == 0) { // login failed
AlertDialog alertDialog = new AlertDialog.Builder(
LoginActivity.this).create();
alertDialog.setTitle("Error");
alertDialog.setMessage("Login failed");
alertDialog.setButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
LoginActivity.this.finish();
dialog.cancel();
}
});
alertDialog.setIcon(android.R.drawable.ic_dialog_info);
alertDialog.show();
} else if(status == 1) { // login success
AlertDialog alertDialog = new AlertDialog.Builder(
LoginActivity.this).create();
alertDialog.setTitle("Success");
alertDialog.setMessage("Login success");
alertDialog.setButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
LoginActivity.this.finish();
dialog.cancel();
}
});
alertDialog.setIcon(android.R.drawable.ic_dialog_info);
alertDialog.show();
}
}
}
}
test_login
布局XMl文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/loginbglayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp" >
<TableLayout
android:id="@+id/holderLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true" >
<TableRow
android:id="@+id/row1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" >
<TextView
android:id="@+id/textViewUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:gravity="right"
android:text="UserName"
android:textColor="#ffffff" />
<EditText
android:id="@+id/editTextUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" >
</EditText>
</TableRow>
<TableRow
android:id="@+id/row2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center" >
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:gravity="right"
android:text="Password"
android:textColor="#ffffff" />
<EditText
android:id="@+id/editTextPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="textPassword" />
</TableRow>
<TableRow
android:id="@+id/row3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center" >
<View
android:layout_width="0dp"
android:layout_height="2dip"
android:layout_weight="1"
android:focusable="false" />
<Button
android:id="@+id/cmdDoLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="Login" >
</Button>
</TableRow>
</TableLayout>
</RelativeLayout>