android-----ANR

来源:互联网 发布:space x 知乎 编辑:程序博客网 时间:2024/05/15 21:01

今天接触到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 {@Overrideprotected 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;@Overrideprotected 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>@Overrideprotected 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);//告诉主线程一个消息:帮我改界面    内容:bitmapMessage 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的模拟器,结果如下所示:

程序就可以正常运行了。


0 0