您的位置:首页 > 移动开发 > Android开发

android-----ANR

2015-08-08 12:02 621 查看
今天接触到Android的ANR,ANR(application not response)即应用程序没有响应。

先上一段代码:

布局代码:

<span style="font-size:18px;"><RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Button
        android:onClick="click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="点我" />

</RelativeLayout></span>
java代码:

<span style="font-size:18px;">public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void click(View v){
		try {
			Thread.sleep(6000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}</span>
运行应用程序,结果如下所示:



为什么会产生这样的原因了?原来主线程(UI线程)需要做很多重要的事情,如响应点击事件、更新UI。

如果在主线程中阻塞过长的时间,应用程序就会无响应。因此,为了避免这种情况的发生就需要:

所有耗时的操作都应该放在子线程中完成。

此外,出现ANR还与Android 的版本有关,在Android4.0以上的版本在设计时就会检查主线程的操作,若主线程耗时过长就会直接出现ANR,但在Android4.0以下就没有这种情况,可能是当时设计时并没有考虑到这种情况。

下面来看看这个示例

布局文件代码:

<span style="font-size:18px;"><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" >

    <ImageView 
        android:id="@+id/iv"
        android:layout_weight="20"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
         />
     <!-- android:hint="请输入图片路径" -->
    <EditText 
         android:id="@+id/et_path"
         android:text="http://c.hiphotos.baidu.com/image/pic/item/0d338744ebf81a4ce3024eb2d42a6059252da69d.jpg"
         android:singleLine="true"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"/>
    
    <Button 
         android:id="@+id/bt"
         android:onClick="openImage"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal"
         android:text="浏览"/>

</LinearLayout></span>


Src代码:

<span style="font-size:18px;">public class MainActivity extends Activity {
	private ImageView iv;
	private EditText et_path;
	private Button bt;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		iv=(ImageView) findViewById(R.id.iv);
		et_path=(EditText) findViewById(R.id.et_path);
		bt=(Button) findViewById(R.id.bt);
	}

	public void openImage(View v){
		String path=et_path.getText().toString().trim();
		if(TextUtils.isEmpty(path)){
			Toast.makeText(this, "图片路径不能为空", 0).show();
		}else{
			try {
				URL url=new URL(path);
				//根据URL发送http请求
				HttpURLConnection conn=(HttpURLConnection) url.openConnection();
				//设置请求方式
				conn.setRequestMethod("GET");
				conn.setConnectTimeout(5000);
				conn.setRequestProperty("Connection", "Keep-Alive");
				
				int code=conn.getResponseCode();
				if(code==200){
					InputStream is=conn.getInputStream();
					Bitmap bitmap= BitmapFactory.decodeStream(is); 
					iv.setImageBitmap(bitmap);
				}else{
					Toast.makeText(this, "显示图片失败", 0).show();
				}
			} catch (Exception e) {
				e.printStackTrace();
				Toast.makeText(this, "获取图片失败", 0).show();
			}
			
		}
		
	}

}</span>
先使用Android2.2模拟器运行程序,结果如下所示:



程序是能够正常运行的

再用Android4.3的模拟器运行程序,结果如下所示:



原因:访问网络的操作只能在子线程中执行,若是在主线程中执行,程序就会弹出ANR

并报以下的警告:



将代码更改如下:

public class MainActivity extends Activity {
	protected static final int CHANGE_UI = 1;
	private ImageView iv;
	private EditText et_path;
	
	//主线程创建一个消息处理器
	<span style="color:#FF0000;">private Handler handler=new Handler(){
		public void handleMessage(Message msg){
			if(msg.what==CHANGE_UI){
				Bitmap bitmap=(Bitmap) msg.obj;
				iv.setImageBitmap(bitmap);
			}
		}
	};</span>

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		iv=(ImageView) findViewById(R.id.iv);
		et_path=(EditText) findViewById(R.id.et_path);
	}

	public void openImage(View v){
		final String path=et_path.getText().toString().trim();
		if(TextUtils.isEmpty(path)){
			Toast.makeText(this, "图片路径不能为空", 0).show();
		}else{
			
			<span style="color:#FF0000;">new Thread(){
				public void run(){
					try {
						URL url=new URL(path);
						//根据URL发送http请求
						HttpURLConnection conn=(HttpURLConnection) url.openConnection();
						//设置请求方式
						conn.setRequestMethod("GET");
						conn.setConnectTimeout(5000);
						conn.setRequestProperty("Connection", "Keep-Alive");
						
						int code=conn.getResponseCode();
						if(code==200){
							InputStream is=conn.getInputStream();
							Bitmap bitmap= BitmapFactory.decodeStream(is); 
							//iv.setImageBitmap(bitmap);
							//告诉主线程一个消息:帮我改界面    内容:bitmap
							Message msg=new Message();
							msg.what=CHANGE_UI;
							msg.obj=bitmap;
							handler.sendMessage(msg);
						}else{
							Toast.makeText(MainActivity.this, "显示图片失败", 0).show();
						}
					} catch (Exception e) {
						e.printStackTrace();
						Toast.makeText(MainActivity.this, "获取图片失败", 0).show();
					}
				}
			}.start();</span>
			
			
		}
		
	}

}
再次运行Android4.3的模拟器,结果如下所示:



程序就可以正常运行了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: