android-----ANR ╰+哭是因爲堅強的太久メ 2022-08-03 13:41 229阅读 0赞 今天接触到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> 运行应用程序,结果如下所示: ![Center][] 为什么会产生这样的原因了?原来主线程(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模拟器运行程序,结果如下所示: ![Center 1][] 程序是能够正常运行的 再用Android4.3的模拟器运行程序,结果如下所示: ![Center 2][] 原因:访问网络的操作只能在子线程中执行,若是在主线程中执行,程序就会弹出ANR 并报以下的警告: ![Center 3][] 将代码更改如下: 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的模拟器,结果如下所示: ![Center 4][] 程序就可以正常运行了。 [Center]: /images/20220731/1921bacdf7c94dfb9fc048625d7aa9ad.png [Center 1]: /images/20220731/67720ae0270647b68015303583d1b3fc.png [Center 2]: /images/20220731/4d541abe45784e8894404ce8cfa7c2a0.png [Center 3]: /images/20220731/c1d37402af8b4a58bd4823179ab35242.png [Center 4]: /images/20220731/3822203618f544f09480fc646fdca8e6.png
还没有评论,来说两句吧...