ANR和消息机制

anr产生的原理&如何避免

ANR : application not response 应用程序无响应

ANR产生的原因 :  

主线程需要做很多重要的事情,如响应点击事件,更新ui

如果在主线程里边阻塞过久的时间,应用程序就会无响应

为了避免出现ANR,所有耗时的操作都应该放在子线程里边执行

public void watch(View view) {

final String path = this.et_path.getText().toString().trim();

if (TextUtils.isEmpty(path)) {

Toast.makeText(this, "路径不能为空", 0).show();

} else {

new Thread() {

@Override

public void run() {

try {

URL url = new URL(path);

HttpURLConnection connection = (HttpURLConnection) url

.openConnection();

// 设置请求方式

connection.setRequestMethod("GET");

// 设置超时时间

connection.setConnectTimeout(10000);

// connection.setRequestProperty(field, newValue)

int code = connection.getResponseCode();

if (code == 200) {

InputStream is = connection.getInputStream();

Bitmap bitmap = BitmapFactory.decodeStream(is);

iv_beauty.setImageBitmap(bitmap);

} else {

Toast.makeText(MainActivity.this, "获取图片失败", 0).show();

}

} catch (Exception e) {

e.printStackTrace();

Toast.makeText(MainActivity.this, "读取图片失败", 0).show();

}

}

}.start();

}

}

此时程序有抛出了异常:

android.view.ViewRootImpl$CalledFromWrongThreadException: 

Only the original thread that created a view hierarchy can touch its views.

说白了,谁创建的view对象,谁才能动它

在安卓系统中,只有主线程才能修改veiw对象

内部实现:更改界面的时候做一个检查,检查这个更新操作是否在主线程的代码执行的,

          如果是,没有任何问题

          不过不是,立刻抛出一个运行时异常 ViewRootImpl$CalledFromWrongThreadException

通过消息机制来解决这个问题

android消息机制入门

public class MainActivity extends Activity {

protected static final int UPDATE_UI = 1;

protected static final int ERROR = 2;

private ImageView iv_beauty;

private EditText et_path;

 // 主线程创建消息处理器

Handler handler = new Handler() {

@Override

public void handleMessage(Message msg) {

if(msg.what == UPDATE_UI) {

iv_beauty.setImageBitmap((Bitmap)msg.obj);

} else {

Toast.makeText(getApplicationContext(), "图片获取失败!", 0).show();

}

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

this.iv_beauty = (ImageView) this.findViewById(R.id.iv_beauty);

this.et_path = (EditText) this.findViewById(R.id.et_path);

}

public void watch(View view) {

final String path = this.et_path.getText().toString().trim();

if (TextUtils.isEmpty(path)) {

Toast.makeText(this, "路径不能为空", 0).show();

} else {

new Thread() {

@Override

public void run() {

try {

URL url = new URL(path);

HttpURLConnection connection = (HttpURLConnection) url

.openConnection();

// 设置请求方式

connection.setRequestMethod("GET");

// 设置超时时间

connection.setConnectTimeout(10000);

// connection.setRequestProperty(field, newValue)

int code = connection.getResponseCode();

if (code == 200) {

InputStream is = connection.getInputStream();

Bitmap bitmap = BitmapFactory.decodeStream(is);

 // 告诉主线程一个消息,帮我更新ui,内容:bitmap

 Message msg = new Message();

msg.what = UPDATE_UI;

msg.obj = bitmap;

handler.sendMessage(msg);

} else {

 Message msg = new Message();

msg.what = ERROR;

handler.sendMessage(msg);

}

} catch (Exception e) {

e.printStackTrace();

 Message msg = new Message();

msg.what = ERROR;

handler.sendMessage(msg);

}

}

}.start();

}

}

}

提交数据到服务器

1.布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical"

    tools:context=".MainActivity" >

    <EditText

        android:id="@+id/et_username"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:hint="请输入用户名" />

    <EditText

        android:id="@+id/et_password"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:hint="请输入密码"

        android:inputType="textPassword" />

    <Button

android:onClick="get"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="get请求登录" />

    

    <Button

android:onClick="post"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="post请求登录" />

    

    <Button

android:onClick="clientGet"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="client get请求登录" />

    

    <Button

android:onClick="clientPost"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="client post请求登录" />

</LinearLayout>

2.Activity

public class MainActivity extends Activity {

private EditText et_userName;

private EditText et_password;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

this.et_userName = (EditText) this.findViewById(R.id.et_username);

this.et_password = (EditText) this.findViewById(R.id.et_password);

}

public void get(View view) {

final String userName = this.et_userName.getText().toString().trim();

final String password = this.et_password.getText().toString().trim();

new Thread() {

public void run() {

final String result = LoginService.loginByGet(userName,

password);

if (result != null) {

/*

 * Runs the specified action on the UI thread. If the

 * current thread is the UI thread, then the action is

 * executed immediately. If the current thread is not the UI

 * thread, the action is posted to the event queue of the UI

 * thread.

 */

runOnUiThread(new Runnable() {

@Override

public void run() {

Toast.makeText(MainActivity.this, result, 0).show();

}

});

} else {

runOnUiThread(new Runnable() {

@Override

public void run() {

Toast.makeText(MainActivity.this, "请求失败。。。。", 0)

.show();

}

});

}

};

}.start();

}

public void post(View view) {

final String userName = this.et_userName.getText().toString().trim();

final String password = this.et_password.getText().toString().trim();

new Thread() {

public void run() {

final String result = LoginService.loginByPost(userName,

password);

if (result != null) {

runOnUiThread(new Runnable() {

@Override

public void run() {

Toast.makeText(MainActivity.this, result, 0).show();

}

});

} else {

runOnUiThread(new Runnable() {

@Override

public void run() {

Toast.makeText(MainActivity.this, "请求失败。。。。", 0)

.show();

}

});

}

};

}.start();

}

public void clientGet(View view) {

final String userName = this.et_userName.getText().toString().trim();

final String password = this.et_password.getText().toString().trim();

new Thread() {

public void run() {

final String result = LoginService.loginByClientGet(userName,

password);

if (result != null) {

runOnUiThread(new Runnable() {

@Override

public void run() {

Toast.makeText(MainActivity.this, result, 0).show();

}

});

} else {

runOnUiThread(new Runnable() {

@Override

public void run() {

Toast.makeText(MainActivity.this, "请求失败。。。。", 0)

.show();

}

});

}

};

}.start();

}

public void clientPost(View view) {

final String userName = this.et_userName.getText().toString().trim();

final String password = this.et_password.getText().toString().trim();

new Thread() {

public void run() {

final String result = LoginService.loginByClientPost(userName,

password);

if (result != null) {

runOnUiThread(new Runnable() {

@Override

public void run() {

Toast.makeText(MainActivity.this, result, 0).show();

}

});

} else {

runOnUiThread(new Runnable() {

@Override

public void run() {

Toast.makeText(MainActivity.this, "请求失败。。。。", 0)

.show();

}

});

}

};

}.start();

}

}

3.业务类

public class LoginService {

/*

 * 采用get方式请求

 */

public static String loginByGet(String userName, String password) {

try {

String path = "http://110.65.99.66:8080/androidserver/WebServlet?userName="

+ URLEncoder.encode(userName, "UTF-8")

+ "&password="

+ URLEncoder.encode(password, "UTF-8");

URL url = new URL(path);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.setReadTimeout(5000);

int code = conn.getResponseCode();

if (code == 200) {

InputStream is = conn.getInputStream();

String result = StreamTool.readInputStream(is);

is.close();

return result;

} else {

return null;

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return null;

}

/*

 * 采用post方式

 */

public static String loginByPost(String userName, String password) {

String path = "http://110.65.99.66:8080/androidserver/WebServlet";

try {

URL url = new URL(path);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("POST");

conn.setReadTimeout(5000);

String params = "userName=" + URLEncoder.encode(userName, "UTF-8")

+ "&password=" + URLEncoder.encode(password, "UTF-8");

// 设置请求

/**

 * application/x-www-form-urlencoded 普通表单数据提交方式 multipart/form-data

 * 文件上传 text/plain 原始文本数据

 */

conn.setRequestProperty("content-type",

"application/x-www-form-urlencoded");

conn.setRequestProperty("content-length", params.length() + "");

conn.setDoOutput(true);

OutputStream outputStream = conn.getOutputStream();

outputStream.write(params.getBytes());

int code = conn.getResponseCode();

if (code == 200) {

InputStream is = conn.getInputStream();

String result = StreamTool.readInputStream(is);

is.close();

return result;

} else {

return null;

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return null;

}

/*

 * 采用HttpGet方式

 */

public static String loginByClientGet(String userName, String password) {

try {

// 1.打开浏览器

HttpClient client = new DefaultHttpClient();

// 2.输入网址

String path = "http://110.65.99.66:8080/androidserver/WebServlet?userName="

+ userName + "&password=" + password;

HttpGet httpGet = new HttpGet(path);

// 3.敲回车

HttpResponse response = client.execute(httpGet);

int code = response.getStatusLine().getStatusCode();

if (code == 200) {

InputStream is = response.getEntity().getContent();

String result = StreamTool.readInputStream(is);

is.close();

return result;

} else {

return null;

}

} catch (Exception e) {

// TODO: handle exception

}

return null;

}

/*

 * 采用HttpPost方式

 */

public static String loginByClientPost(String userName, String password) {

try {

// 1.打开浏览器

HttpClient client = new DefaultHttpClient();

// 2.输入网址

String path = "http://110.65.99.66:8080/androidserver/WebServlet";

HttpPost httpPost = new HttpPost(path);

// 3.设置参数

ArrayList<NameValuePair> parameters = new ArrayList<NameValuePair>();

parameters.add(new BasicNameValuePair("userName", userName));

parameters.add(new BasicNameValuePair("password", password));

httpPost.setEntity(new UrlEncodedFormEntity(parameters, "utf-8"));

// 4.敲回车

HttpResponse response = client.execute(httpPost);

int code = response.getStatusLine().getStatusCode();

if (code == 200) {

InputStream is = response.getEntity().getContent();

String result = StreamTool.readInputStream(is);

is.close();

return result;

} else {

return null;

}

} catch (Exception e) {

// TODO: handle exception

}

return null;

}

}

原文地址:https://www.cnblogs.com/freenovo/p/4469831.html