Android中四大组件以及如何避免anr

一个Android程序有四大基本组件,但只有activity是必须有的


1,activity:可视化的交互界面,   为一个Android程序添加一个activity的步骤是

             第一步:新建一个类继承自activity,  并且为该activity设置布局文件  

<span style="font-size:14px;">public class MyNext extends Activity {
             ......
         setContentView(R.layout.activity_next);
      }</span>

      

            第二步,在Androidmanifest.xml清单文件中配置该activity

<span style="font-size:14px;">  <activity android:name=".activity.MyNext"/></span></span>

   至此,一个新的activity就添加成功了,一个activity的生命周期为:onCreate,onStart,onResume,onPause,onStop,onDestroy

 

2,service:服务,无界面,生命周期长,不可见,可运行在后台的组件,为一个Android程序添加服务的步骤是

             第一步:新建一个类继承自Service

 

<span style="font-size:14px;">     public class MyService extends Service {
            ......
       }</span>

              第二步,在Androidmanifest.xml清单文件中进行配置该service

   <span style="font-size:14px;">  <service
            android:name=".MyService"/></span>

               第三步,在activity中开启服务

                开启服务的方式 有两种

                第一种:   利用startService开启的服务与 访问者相互独立,必须调用stopService 来结束服务

<span style="font-size:14px;">         //开启服务             
            startService(new Intent(MyNext.this,MyService.class));
           //结束服务            
             stopService(new Intent(MyNext.this,MyService.class));</span>
 
 


利用 这种方式开启服务时其生命周期为:onCreate-->onStartCommand--->onDestroy,当我多次调用startService时,如果服务已经被创建则只会调用onStartCommand方法,若未创建则去调用onCreate。。。。

<span style="font-size:14px;">12-16 11:09:38.154  21909-21909/com.example.yong.myfirstdemo I/tag﹕ 调用的方法是->>onCreate---com.example.yong.myfirstdemo.MyService
12-16 11:09:38.154  21909-21909/com.example.yong.myfirstdemo I/tag﹕ 调用的方法是->>onStartCommand---com.example.yong.myfirstdemo.MyService
12-16 11:09:40.599  21909-21909/com.example.yong.myfirstdemo I/tag﹕ 调用的方法是->>onStartCommand---com.example.yong.myfirstdemo.MyService
12-16 11:09:40.898  21909-21909/com.example.yong.myfirstdemo I/tag﹕ 调用的方法是->>onStartCommand---com.example.yong.myfirstdemo.MyService
12-16 11:09:43.090  21909-21909/com.example.yong.myfirstdemo I/tag﹕ 调用的方法是->>onyDestroy---com.example.yong.myfirstdemo.MyService</span>

                      第二种:  利用bindService开启服务,该服务依赖于访问者而存在,  若访问者退出则服务结束,所以如果要求服务和访问者 同时结束,不需要调用任何方法去结束服务。如果想要在访问者未 结束时就结束服务,需要调用unbindService方法。


            <span style="font-size:14px;">  //开启服务
                bindService(new Intent(MyNext.this,MyService.class), serviceConnection, BIND_AUTO_CREATE);
                //关闭服务,参数与开启服务中的serviceConnection为同一个,若不相同,会出现如下错误
                unbindService(serviceConnection);</span>

当bindservice方法与unbindService方法的参数serviceConnection使用的不同时会出现如下错误,如果出现如下I错去,那就要检查一下serviceConnection是不是在unbindService时重新创建了一次:

<span style="font-size:14px;">java.lang.IllegalArgumentException: Service not registered: com.example.yong.myfirstdemo.activity.MyNext$MyServiceConn@411c3870
            at android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:959)
            at android.app.ContextImpl.unbindService(ContextImpl.java:1574)
            at android.content.ContextWrapper.unbindService(ContextWrapper.java:484)
            at com.example.yong.myfirstdemo.activity.MyNext.onClick(MyNext.java:191)
            at android.view.View.performClick(View.java:4222)
            at android.view.View$PerformClick.run(View.java:17624)
            at android.os.Handler.handleCallback(Handler.java:800)
            at android.os.Handler.dispatchMessage(Handler.java:100)
            at android.os.Looper.loop(Looper.java:194)
            at android.app.ActivityThread.main(ActivityThread.java:5398)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:836)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:603)
            at dalvik.system.NativeStart.main(Native Method)</span>
                        用这种方式开启服务时服务的生命周期为:onCreate-->onBind-->onUnbind-->onDestroy,在服务创建后,我调用多次bindService方法,不会再去调用onCreate  和onBind方法。。在服务创建后不论是退出activity还是调用unbindService方法都会去调用onUnbind和onDestroy方法
<span style="font-size:14px;">12-16 11:12:57.410  22870-22870/com.example.yong.myfirstdemo I/tag﹕ 调用的方法是->>onCreate---com.example.yong.myfirstdemo.MyService
12-16 11:12:57.411  22870-22870/com.example.yong.myfirstdemo I/tag﹕ 调用的方法是->>onBind---com.example.yong.myfirstdemo.MyService
12-16 11:13:06.918  22870-22870/com.example.yong.myfirstdemo I/tag﹕ 调用的方法是->>onUnbind---com.example.yong.myfirstdemo.MyService
12-16 11:13:06.922  22870-22870/com.example.yong.myfirstdemo I/tag﹕ 调用的方法是->>onyDestroy---com.example.yong.myfirstdemo.MyService</span>

                   但是如果未调用bindService方法,就 调用unbindService方法,则会出现以下异常:

<span style="font-size:14px;">java.lang.IllegalArgumentException: Service not registered: com.example.yong.myfirstdemo.activity.MyNext$MyServiceConn@412019c0
            at android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:959)
            at android.app.ContextImpl.unbindService(ContextImpl.java:1574)
            at android.content.ContextWrapper.unbindService(ContextWrapper.java:484)
            at com.example.yong.myfirstdemo.activity.MyNext.onClick(MyNext.java:186)
            at android.view.View.performClick(View.java:4222)
            at android.view.View$PerformClick.run(View.java:17624)
            at android.os.Handler.handleCallback(Handler.java:800)
            at android.os.Handler.dispatchMessage(Handler.java:100)
            at android.os.Looper.loop(Looper.java:194)
            at android.app.ActivityThread.main(ActivityThread.java:5398)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:836)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:603)
            at dalvik.system.NativeStart.main(Native Method)</span>

                   如果出现上述异常,仅仅是因为未绑定服务,可以用try/catch语句来提醒用户还未绑定服务

  <span style="font-size:14px;">          try {
                    unbindService(serviceConnection);
                } catch (IllegalArgumentException e) {
                    //异常处理代码
                    Log.i("tag","还未绑定服务");
                }</span>

3,BroadcastReceiver,广播接收器,广播接收器只有一个方法onReceive,广播接收器组件用法如下:

      第一步:自定义一个类,继承自BroadcastReceiver,并重写onReceive方法,代码如下:

        

<span style="font-size:14px;"> class MyBroadCastReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            //监听到广播时的代码
            Log.i("tag", "调用的方法是->>onReceive" + "---" + getClass().getName());
        }
    }</span>

         第二步,注册广播,和服务类似,广播的注册有两种形式,

               第一种,在Androidmanifest.xml文件中注册

       <span style="font-size:14px;">  <receiver android:name=".MyBroadCastReceiver">
            <intent-filter>
                <action android:name="com.receiver"/>
            </intent-filter>
        </receiver></span>

                第二种方式,在代码中注册,

                 

<span style="font-size:14px;">     IntentFilter filter = new IntentFilter("com.receiver");
    MyBroadCastReceiver mBroadCastReceiver = new MyBroadCastReceiver();</span>

                    
<span style="font-size:14px;">              //注册广播
                registerReceiver(mBroadCastReceiver, filter);
                //撤销广播
                unregisterReceiver(mBroadCastReceiver);</span>

       广播注册成功后,我们可以发送广播
<span style="font-size:14px;">               //发送广播
               sendBroadcast(new Intent("com.receiver"));</span>

正如Service中bindService与unbindService必须成对出现,广播中registerReceiver与unregisterReceiver也必须成对出现,如果出现以下错误:
<span style="font-size:14px;"> java.lang.IllegalArgumentException: Receiver not registered: com.example.yong.myfirstdemo.MyBroadCastReceiver@411d37f8
            at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:665)
            at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1462)
            at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:445)
            at com.example.yong.myfirstdemo.activity.MyNext.onClick(MyNext.java:202)
            at android.view.View.performClick(View.java:4222)
            at android.view.View$PerformClick.run(View.java:17624)
            at android.os.Handler.handleCallback(Handler.java:800)
            at android.os.Handler.dispatchMessage(Handler.java:100)
            at android.os.Looper.loop(Looper.java:194)
            at android.app.ActivityThread.main(ActivityThread.java:5398)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:836)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:603)
            at dalvik.system.NativeStart.main(Native Method)</span>

可以从两个方向去考虑,第一,在调用unregisterReceiver之前是否没有调用registerReceiver方法,第二,两个方法中的参数是否为同一个。。。如果是第一种情况,可以向处理service出现异常时的解决方案一样,在调用unregisterReceiver方法时进行try/catch,
try {
                    unregisterReceiver(mBroadCastReceiver);
                }catch (IllegalArgumentException e){
                    //广播未注册时的处理代码
               } 

注册广播有两种方式,各有利弊

1,在xml中注册,属于常驻型广播,广播在应用开启前注册,在应用结束后,仍旧存在,不随着activity的结束而终止

2,在代码中注册,属于非常驻型,存活周期受activity影响,方便管理

总结:

     面试必备的一个问题:如何去避免anr?anr是说程序无响应,是由于耗时操作造成 的,那么如何更好的避免呢?

    首先,哪些属于耗时操作?    网络操作,大文件的拷贝,阻塞式的请求等属于耗时操作。。

     activity属于可视化的用户交互界面,在activity的UI线程中执行耗时操作,或造成卡顿现象,直接影响用户体验,可以在activity中开启线程去进行耗时操作, 用AsyncTask解决。

      广播接收器的onReceive方法执行时间特别短只有不到10s,这也就意味着无法在广播接收器中进行耗时操作,而且因为onReceive方法时间太短也无法去开启子线程来进行耗时操作,所以可以在onReceive方法中开启服务,在服务中进行耗时操作。


4,ContentProvider,内容提供者,两个程序之间共享私有数据












  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值