现在的位置: 首页 > 综合 > 正文

android 常识

2018年04月12日 ⁄ 综合 ⁄ 共 10465字 ⁄ 字号 评论关闭

http://blog.csdn.net/trust555/article/details/9102525

http://blog.163.com/wapuzxl%40126/blog/static/137249957201131585557142/

#1 安卓线程模型

关于安卓线程模型,可以查看 ppt: http://pan.baidu.com/s/1gd7xwEf

一个应用程序启动的时候,会启动一个新的linux进程和一个线程。默认情况下,一个应用程序的所有组件运行在一个进程和主线程内。不过,你可以通过manifest来指定组件运行在多个进程中。
在manifest中,application和四个主要组件:activity,service, receiver,provider都可以利用android:process属性制定运行在那个进程中。
Android在内存不足的情况下,有可能主动杀掉某个进程。进程的相对重要性可以分为几个层次:
1.Foreground process:
- Activity: OnResume() is called
- Service: bound to an Activity whose OnResume is called.
- Service: startForeground is called;
- Service: Executing lifecycle callbacks(onCreate(), onStart(),onDestroy())
- BroadcastReceiver: executing onReceive()
2. Visiable process:
- Activity: onPause() is called
- Service: bound to a visiable activity
3. Service Process
- Running a service that has been started with startServcice
4. Background process
- Activity: onStop() is called
5. Empty process:
- no activte component
从上面的表可以看出,activity的后台线程并不会影响activity的重要级别。因此,后台工作应由service来完成。
 
应用程序启动后会启动一个主线程(main thread),这个线程会处理与用户的交互,因此也被称作UI thread.
同一个进程的所有的组件(component)在main thread(UI thread)中被实例化,所有对组件的系统调用都由该进程执行。因此,所有的系统callback如onKeyDown()和lifecycle callback都运行在main thread内。UI的绘制也运行在这个线程内。
基于该单线程模型,由两个要求:
Do not block the UI thread
Do not access the Android UI toolkit from outside the UI thread


工作线程(background/worker threads)
由于UI thread不是线程安全的,因此从工作线程中操作UI对象可以采用下面的方法:
1. 向UI线程发送Runnable对象。 该方法使用简单,对对象多了以后维护很复杂
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
2. 在work thread中使用Handler来处理来自UI thread的消息
3. 最佳方案: 继承AsyncTask
AsyncTask在worker thread中运行,结束后向UI thread发送结果,而无需显示处理进程和handler.
使用方法:
a. 继承AsyncTask,实现doInBackgroud(),onPostExecute()
b. 在UI thread中调用该AsyncTask()实例的Execute().
Example:
 public void onClick(View v) {
    new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected Bitmap doInBackground(String... urls) {
        return loadImageFromNetwork(urls[0]);
    }
   
    /** The system calls this to perform work in the UI thread and delivers
      * the result from doInBackground() */
    protected void onPostExecute(Bitmap result) {
        mImageView.setImageBitmap(result);
    }
}
    worker thread使用的一个需要注意的问题是worker thread可能因为runtime configuration change被意外重启.RCC的原因可能是screen orientation, keyboard availability, and language



#2 如何启用Service,如何停用Service。

Android中的service类似于windows中的service,service一般没有用户操作界面,它运行于系统中不容易被用户发觉,
可以使用它开发如监控之类的程序。
一。步骤
第一步:继承Service
public class SMSService extends Service { }
第二步:在AndroidManifest.xml文件中的<application>节点里对服务进行配置:
<service android:name=".DemoService" />
二。Context.startService()Context.bindService
服务不能自己运行,需要通过调用Context.startService()Context.bindService()方法启动服务。这两个方法都可
以启动Service,但是它们的使用场合有所不同。
1.使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。
使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。
2.采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,
接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并
不会导致多次创建服务,但会导致多次调用onStart()方法。
采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用
onDestroy()方法。


3.采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,
接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,
。接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会
导致多次创建服务及绑定(也就是说onCreate()onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务
解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。


备注:
1. 采用startService()启动服务
     Intent intent =new Intent(DemoActivity.this, DemoService.class);
    startService(intent);
2.Context.bindService()启动
    Intent intent =new Intent(DemoActivity.this, DemoService.class);
   bindService(intent, conn, Context.BIND_AUTO_CREATE);
   //unbindService(conn);//解除绑定


2 注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。   

Android广播机制(两种注册方法)
在android下,要想接受广播信息,那么这个广播接收器就得我们自己来实现了,我们可以继承BroadcastReceiver,就可以有一个广播接受器了。有个接受器还不够,我们还得重写BroadcastReceiver里面的onReceiver方法

public class SmsBroadCastReceiverextends BroadcastReceiver   
 

   @Override  
   public void onReceive(Context context, Intent intent)   
     
       Bundle bundle = intent.getExtras();  
       Object[] object = (Object[])bundle.get("pdus");   
       SmsMessage sms[]=new SmsMessage[object.length];   
       for(int i=0;i<object.length;i++)  
       {   
            sms[0] =SmsMessage.createFromPdu((byte[])object);  
            Toast.makeText(context, "来自"+sms.getDisplayOriginatingAddress()+"的消息是:"+sms.getDisplayMessageBody(),Toast.LENGTH_SHORT).show();   
       }   
       //终止广播,在这里我们可以稍微处理,根据用户输入的号码可以实现短信防火墙。   
       abortBroadcast();   
     
      


当实现了广播接收器,还要设置广播接收器接收广播信息的类型,这里是信息:android.provider.Telephony.SMS_RECEIVED

我们就可以把广播接收器注册到系统里面,可以让系统知道我们有个广播接收器。这里有两种,一种是代码动态注册:

//生成广播处理  
smsBroadCastReceiver = newSmsBroadCastReceiver();   
//实例化过滤器并设置要过滤的广播  
IntentFilter intentFilter = newIntentFilter("android.provider.Telephony.SMS_RECEIVED");
//注册广播   
BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver,intentFilter);  


一种是在AndroidManifest.xml中配置广播

...

  <receiver
android:name=".SmsBroadCastReceiver">  

            <intent-filterandroid:priority="20">  
                <actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/>  
            </intent-filter>  
       </receiver>       
   </application>  


两种注册类型的区别是:
    1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。
    2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。


47.    请解释下在单线程模型中Message、Handler、MessageQueue、Looper之间的关系。

Handler简介:
一个Handler允许你发送和处理MessageRunable对象,这些对象和一个线程的MessageQueue相关联。每一个线程实例和一个单独的线程以及该线程的MessageQueue相关联。当你创建一个新的Handler时,它就和创建它的线程绑定在一起了。这里,线程我们也可以理解为线程的MessageQueue。从这一点上来看,HandlerMessageRunable对象传递给MessageQueue,而且在这些对象离开MessageQueue时,Handler负责执行他们。

Handler有两个主要的用途:(1)确定在将来的某个时间点执行一个或者一些MessageRunnable对象。(2)在其他线程(不是Handler绑定线程)中排入一些要执行的动作。

Scheduling Message,即(1),可以通过以下方法完成:
post(Runnable):Runnable
handler绑定的线程上执行,也就是说不创建新线程。
postAtTime(Runnable,long):
postDelayed(Runnable,long):
sendEmptyMessage(int):
sendMessage(Message):
sendMessageAtTime(Message,long):
sendMessageDelayed(Message,long):
post
这个动作让你把Runnable对象排入MessageQueue,MessageQueue受到这些消息的时候执行他们,当然以一定的排序。sendMessage这个动作允许你把Message对象排成队列,这些Message对象包含一些信息,HandlerhanlerMessage(Message)会处理这些Message.当然,handlerMessage(Message)必须由Handler的子类来重写。这是编程人员需要作的事。

posting或者sending到一个Hanler时,你可以有三种行为:当MessageQueue准备好就处理,定义一个延迟时间,定义一个精确的时间去处理。后两者允许你实现timeout,tick,和基于时间的行为。

当你的应用创建一个新的进程时,主线程(也就是UI线程)自带一个MessageQueue,这个MessageQueue管理顶层的应用对象(像activities,broadcast
receivers
等)和主线程创建的窗体。你可以创建自己的线程,并通过一个Handler和主线程进行通信。这和之前一样,通过postsendmessage来完成,差别在于在哪一个线程中执行这么方法。在恰当的时候,给定的RunnableMessage将在HandlerMessageQueue中被Scheduled

Message简介:
Message
类就是定义了一个信息,这个信息中包含一个描述符和任意的数据对象,这个信息被用来传递给Handler.Message对象提供额外的两个int域和一个Object域,这可以让你在大多数情况下不用作分配的动作。
尽管Message的构造函数是public的,但是获取Message实例的最好方法是调用Message.obtain(),或者Handler.obtainMessage()方法,这些方法会从回收对象池中获取一个。

MessageQueue简介:
这是一个包含message列表的底层类。Looper负责分发这些messageMessages并不是直接加到一个MessageQueue中,而是通过MessageQueue.IdleHandler关联到Looper
你可以通过Looper.myQueue()从当前线程中获取MessageQueue

Looper简介:
Looper
类被用来执行一个线程中的message循环。默认情况,没有一个消息循环关联到线程。在线程中调用prepare()创建一个Looper,然后用loop()来处理messages,直到循环终止。

大多数和message loop的交互是通过Handler

下面是一个典型的带有Looper的线程实现。
  class LooperThread extends Thread {
      public Handler mHandler;
      
      public void run() {
          Looper.prepare();
          
          mHandler = new Handler() {
              public voidhandleMessage(Message msg) {
                  // process incomingmessages here
              }
          };
          
          Looper.loop();
      }
  }

48.       AIDL的全称是什么?如何工作?能处理哪些类型的数据?

AIDL的英文全称是Android Interface Define Language
A进程要去调用B进程中的service时,并实现通信,我们通常都是通过AIDL来操作的
A工程:
首先我们在net.blogjava.mobile.aidlservice包中创建一个RemoteService.aidl文件,在里面我们自定义一个接口,含有方法getADT插件会在gen目录下自动生成一个RemoteService.java文件,该类中含有一个名为RemoteService.stub的内部类,该内部类中含有aidl文件接口的get方法。
说明一:aidl文件的位置不固定,可以任意
然后定义自己的MyService类,在MyService类中自定义一个内部类去继承RemoteService.stub这个内部类,实现get方法。在onBind方法中返回这个内部类的对象,系统会自动将这个对象封装成IBinder对象,传递给他的调用者。
其次需要在AndroidManifest.xml文件中配置MyService类,代码如下:
<!-- 注册服务 -->  
<service android:name=".MyService"> 
  <intent-filter> 
   <!--  指定调用AIDL服务的ID  -->
       <actionandroid:name="net.blogjava.mobile.aidlservice.RemoteService" />
   </intent-filter> 
</service>
为什么要指定调用AIDL服务的ID,就是要告诉外界MyService这个类能够被别的进程访问,只要别的进程知道这个ID,正是有了这个ID,B工程才能找到A工程实现通信。
说明:AIDL并不需要权限
B工程:
      首先我们要将A工程中生成的RemoteService.java文件拷贝到B工程中,在bindService方法中绑定aidl服务
      绑定AIDL服务就是将RemoteServiceID作为intentaction参数。
      说明:如果我们单独将RemoteService.aidl文件放在一个包里,那个在我们将gen目录下的该包拷贝到B工程中。如果我们将RemoteService.aidl文件和我们的其他类存放在一起,那么我们在B工程中就要建立相应的包,以保证RmoteService.java文件的报名正确,我们不能修改RemoteService.java文件
         bindService(newInten("net.blogjava.mobile.aidlservice.RemoteService"),serviceConnection, Context.BIND_AUTO_CREATE);
      ServiceConnectiononServiceConnected(ComponentName name, IBinderservice)方法中的service参数就是A工程中MyService类中继承了RemoteService.stub类的内部类的对象。

55.     简要解释一下activity、 intent 、intent filter、service、Broadcase、BroadcaseReceiver
  答:一个activity呈现了一个用户可以操作的可视化用户界面 

  一个service不包含可见的用户界面,而是在后台无限地运行 

  可以连接到一个正在运行的服务中,连接后,可以通过服务中暴露出来的借口与其进行通信 

  一个broadcast receiver是一个接收广播消息并作出回应的component,broadcastreceiver没有界面 

  intent:content provider在接收到ContentResolver的请求时被激活。 

  activity, service和broadcast receiver是被称为intents的异步消息激活的。 

一个intent是一个Intent对象,它保存了消息的内容。对于activity和service来说,它指定了请求的操作名称和待操作数据的URI 

  Intent对象可以显式的指定一个目标component。如果这样的话,android会找到这个component(基于manifest文件中的声明)并激活它。但如果一个目标不是显式指定的,android必须找到响应intent的最佳component。

  它是通过将Intent对象和目标的intent filter相比较来完成这一工作的。一个component的intent filter告诉android该component能处理的intent。intent filter也是在manifest文件中声明的。


56.      IntentService有何优点? 
  答:IntentService 的好处 

  * Acitivity的进程,当处理Intent的时候,会产生一个对应的Service 

  * Android的进程处理器现在会尽可能的不kill掉你 

  * 非常容易使用 


59.     Android引入广播机制的用意? 
  答:a:从MVC的角度考虑(应用程序内) 

 其实回答这个问题的时候还可以这样问,android为什么要有那4大组件,现在的移动开发模型基本上也是照搬的web那一套MVC架构,只不过是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一种补充关系,引入广播机制可以方便几大组件的信息和数据交互。

  b:程序间互通消息(例如在自己的应用程序内监听系统来电) 

  c:效率上(参考UDP的广播协议在局域网的方便性) 

  d:设计模式上(反转控制的一种应用,类似监听者模式)


60.     Android
dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念 

  DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念。


67.     说说mvc模式的原理,它在android中的运用 
 MVC(Model_view_contraller)”模型_视图_控制器”。 MVC应用程序总是由这三个部分组成。Event(事件)导致Controller改变Model或View,或者同时改变两者。只要Controller改变了Models的数据或者属性,所有依赖的View都会自动更新。


70.    谈谈Android的IPC

(进程间通信)机制 IPC是内部进程通信的简称,是共享"命名管道"的资源。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互,故在Android中该机制,只适用于Activity和Service之间的通信,类似于远程方法调用,类似于C/S模式的访问。通过定义AIDL接口文件来定义IPC接口。Servier端实现IPC接口,Client端调用IPC接口本地代理。

转载地址:http://blog.csdn.net/linux_loajie/article/details/7661722

抱歉!评论已关闭.