zoukankan      html  css  js  c++  java
  • android面试题-简答题(一)

    1、在多线程编程这块,我们经常要使用Handler,Thread和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢?

    答:Android的CPU分配的最小单元是线程,Handler一般是在某个线程里创建的,因而Handler和Thread就是相互绑定的,一一对应。而Runnable是一个接口,Thread是Runnable的子类。所以说,他俩都算一个进程。HandlerThread顾名思义就是可以处理消息循环的线程,他是一个拥有Looper的线程,可以处理消息循环。与其说Handler和一个线程绑定,不如说Handler是和Looper一一对应的。最后需要说明的是,在UI线程(主线程)中:   mHandler=new Handler(); 

    mHandler.post(new Runnable(){

      void run(){

      //执行代码...}

      });

      这个线程其实是在UI线程之内运行的,并没有新建线程。

      常见的新建线程的方法是:

      Thread thread = new Thread();

      thread.start();

      HandlerThread thread = newHandlerThread("string");

      thread.start();

    2、如何设定应用程序为系统级别的应用?

    答:apk 获取system权限;如何获取如下:

    解释连接:http://blog.csdn.net/superkris/article/details/7709504

     第一个方法简单点,不过需要在Android系统源码的环境下用make来编译:

           1. 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。

           2. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行

           3. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。

           第二个方法是直接把eclipse编出来的apk用系统的签名文件签名

           1. 加入android:sharedUserId="android.uid.system"这个属性。

           2. 使用eclipse编译出apk文件。

           3. 使用目标系统的platform密钥来重新给apk文件签名。首先找到密钥文件,在我ndroid源码目录中的位置是"build/target/product/security",下面的platform.pk8和platform.x509.pem两个文件。然后用Android提供的Signapk工具来签名,signapk的源代码是在"build/tools/signapk"下,编译后在out/host/linux-x86/framework下,用法为java -jarsignapk.jar  platform.x509.pem platform.pk8 input.apk output.apk"。

           加入android:sharedUserId="android.uid.system"这个属性。通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就有权限来修改系统时间了。

           只是加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中还要有目标系统的platform key,就是上面第二个方法提到的platform.pk8和platform.x509.pem两个文件。用这两个key签名后apk才真正可以放入系统进程中。第一个方法中加入LOCAL_CERTIFICATE :=platform其实就是用这两个key来签名。

           这也有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到platform.pk8和platform.x509.pem两个文件。要是别家公司做的Android上连安装都安装不了。试试原始的Android中的key来签名,程序在模拟器上运行OK,不过放到G3上安装直接提示"Package... has no signatures that match those in shared user android.uid.system",这样也是保护了系统的安全。

    3、谈谈Android的IPC(进程间通信)机制

    答:http://blog.csdn.net/luoshengyang/article/details/6618363

    Android系统中,每一个应用程序都是由一些Activity和Service组成的,这些Activity和Service有可能运行在同一个进程中,也有可能运行在不同的进程中,android的IPC机制也就是Binder机制,Android系统是基于Linux内核的,而Linux内核继承和兼容了丰富的Unix系统进程间通信(IPC)机制, 但是,Android系统没有采用上述提到的各种进程间通信机制,而是采用Binder机制,Binder是一种进程间通信机制,它是一种类似于COM和CORBA分布式组件架构,通俗一点,其实是提供远程过程调用(RPC)功能。从英文字面上意思看,Binder具有粘结剂的意思,那么它把什么东西粘结在一起呢?在Android系统的Binder机制中,由一系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序,其中Client、Server和Service Manager运行在用户空间,Binder驱动程序运行内核空间。Binder就是一种把这四个组件粘合在一起的粘结剂了,其中,核心组件便是Binder驱动程序了,Service Manager提供了辅助管理的功能,Client和Server正是在Binder驱动和ServiceManager提供的基础设施上,进行Client-Server之间的通信;

       1. Client、Server和Service Manager实现在用户空间中,Binder驱动程序实现在内核空间中

      2. Binder驱动程序和Service Manager在Android平台中已经实现,开发者只需要在用户空间实现自己的Client和Server

       3.Binder驱动程序提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager通过open和ioctl文件操作函数与Binder驱动程序进行通信

      4. Client和Server之间的进程间通信通过Binder驱动程序间接实现

       5. Service Manager是一个守护进程,用来管理Server,并向Client提供查询Server接口的能力

    4、apk安装卸载的原理

    答:http://blog.csdn.net/lizhiguo0532/article/details/7077432

         http://www.itivy.com/android/archive/2011/8/10/android-apk-setup-method-and-principles.html

    APK安装可以通过以下四种方式:
    1. 系统应用安装,开机时完成系统应用的检查,没安装就安装,安装就跳过,无安装界面。
    2. 网络下载应用安装,通过market应用完成,无安装界面。
    3. ADB工具安装,无安装界面
    4. 通过SD卡来安装apk,有安装界面,由packageinstaller.apk应用处理安装及卸载过程的界面。

    应用安装涉及到如下几个目录:
    system/app     系统自带的应用程序,无法删除
    data/app     用户程序安装的目录,有删除权限
    data/data     存放应用程序的数据
    Data/dalvik-cache   将apk中的dex文件安装到dalvik-cache目录下
    (dex文件是dalvik虚拟机的可执行文件,其大小约为原始apk文件大小的四分之一)

    安装过程:复制APK安装包到data/app目录下,解压并扫描安装包,把dex文件(Dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。

     卸载过程:删除安装过程中在上述三个目录下创建的文件及目录。

    5、如何做适配

    1)android有H、L、M、X、XX四个不同的文件夹存放不同分辨率的图片,系统会自动加载

    2) 偏移量d的设置可以在values-hpdi,values-mdpi,values-ldpi三种文件夹中的dimens.xml文件进行设置

    值得一提的是:

        <dimen name=“bitmap_common_topoffset”>40dp</dimen>

        <dimen name=“bitmap_common_bottomoffset”>-14dp</dimen>

    这里的负数是完全起作用的,系统会认为它是一个负值

    3)各大手机厂商对于Android操作系统都有或多或少的改动,当然这些改动会对我们应用程序产生某些影响

     比如:

      (1)系统源代码中连接music服务的aidl文件所在包名:com.android.music 

      (2)LG则可能将该aidl文件修改所在的包(例如修改为 com.android.music.player),并且修改其中的文件内容(增加一个方法,或者减少几个方法,或者修改方法名称)那么我们的应用要想在LG的手机上发布,那么我们就必须改变所要连接的aidl文件,必须跟LG厂商修改的完全一致。

     

    6、是否进行过apk反编译,如何防止反编译

    反编译:

         Android反编译工具

    ·       dex2jar + jdgui

    ·       apktool

    防止反编译:

    ·       代码加密

    这方式,也只能想想,一旦你自己加密了,Android系统都不认识你了,还怎么运行?(如果有那估计就是eoe现在推的爱加密吧).

    ·       代码混淆

    这种方式,其实我不大愿意将他归类于防止反编译,从Android、Java编译原理上来说,针对自身代码做混淆等操作,必然防止不了反编译这个事实。他能做到的就是将字符,函数等混淆成各种a,b,c,d,1,2,3等。

    这种方式一般称为,
    妨碍对反编译代码的阅读、观看和理解

    Android中主要是针对 proguard.cfg 的配置来实现。

    具体的实现网上针对这部分的解释已经太多,所以这里不详细介绍了。

    ·       动态加载类

    这种方式的启发是根据web端来的。Web端你要防止,那就不发布呗。

    所以我们可以将我们重要的源码,丢在服务器上,必要的时候通过DexClassLoader类去加载重要类。来防止核心代码被反编译。

    具体可看DexClassLoader示例

    ·       用NDK开发核心代码

    从上面已经能知道,C/C++等编译型语言的反汇编难度。所以我们可以放心的使用NDK去开发,生成SO库文件再来调用。

    PS:部分资源文件若十分珍贵,可以通过 #include直接编译到库里(当然内存可能就大了),这种方式可以自己考虑。

     

    7、Android的动画分类以及两种动画的阐述

    Tween动画

            又称“补间动画”、“中间动画”,最早接触Tween类是在学习Flash时候,使用ActionScript做动画的时候,使用过类Tween。

            Tween动画主要的功能是在绘制动画前设置动画绘制的轨迹,包括时间, 位置 ,等等。但是Tween动画的缺点是它只能设置起始点与结束点的两帧,中间过程全部由系统帮我们完成。所以在帧数比较多的游戏开发中是不太会用到它的。
           Tween一共提供了4中动画的效果

           Scale:缩放动画
           Rotate:旋转动画
           Translate:移动动画
           Alpha::透明渐变动画

    Frame动画

           又称帧动画,主要显示方式是<animation-list>为动画的总标签,这里面放着帧动画<item>标签,也就是说若干<item>标签的帧 组合在一起就是帧动画了。<animation-list > 标签中android:oneshot="false"这是一个非常重要的属性,默认为false 表示 动画循环播放, 如果这里写true 则表示动画只播发一次。 <item>标签中记录着每一帧的信息android:drawable="@drawable/a"表示这一帧用的图片为"a",下面以此类推。 android:duration="100" 表示这一帧持续100毫秒,可以根据这个值来调节动画播放的速度。

     8、AIDL全称,如何工作,可处理那些数据

    答:AIDL的英文全称是Android Interface Define Language
    当A进程要去调用B进程中的service时,并实现通信,我们通常都是通过AIDL来操作的
    A工程:
    首先我们在net.blogjava.mobile.aidlservice包中创建一个RemoteService.aidl文件,在里面我们自定义一个接口,含有方法get。ADT插件会在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服务就是将RemoteService的ID作为intent的action参数。
          说明:如果我们单独将RemoteService.aidl文件放在一个包里,那个在我们将gen目录下的该包拷贝到B工程中。如果我们将RemoteService.aidl文件和我们的其他类存放在一起,那么我们在B工程中就要建立相应的包,以保证RmoteService.java文件的报名正确,我们不能修改RemoteService.java文件
             bindService(newInten("net.blogjava.mobile.aidlservice.RemoteService"),serviceConnection,Context.BIND_AUTO_CREATE);
          ServiceConnection的onServiceConnected(ComponentName name, IBinderservice)方法中的service参数就是A工程中MyService类中继承了RemoteService.stub类的内部类的对象。

    9、Android系统中GC什么情况下不会出现内存泄露

    1. 数据库的cursor没有关闭

    2.构造adapter时,没有使用缓存contentview
       衍生listview的优化问题-----减少创建view的对象,充分使用contentview,可以使用一静态类来优化处理getview的过程/

    3.Bitmap对象不使用时采用recycle()释放内存

    4.activity中的对象的生命周期大于activity
    调试方法: DDMS==> HEAPSZIE==>dataobject==>[TotalSize]

     

    10、什么情况会导致Force Close ?如何避免?能否捕获导致其的异常?
    答:一般像空指针啊,可以看起logcat,然后对应到程序中 来解决错误

    11、activity的4种模式,以及不同模式的作用。

    http://blog.csdn.net/zhangjg_blog/article/details/10923643

    activity有四种启动模式,分别为standard,singleTop,singleTask,singleInstance。如果要使用这四种启动模式,必须在manifest文件中<activity>标签中的launchMode属性中配置,如:

    <activity android:name=".app.InterstitialMessageActivity"  
              android:label="@string/interstitial_label"  
              android:theme="@style/Theme.Dialog"  
              android:launchMode="singleTask"  
    </activity> 

    standard

    标准启动模式,也是activity的默认启动模式。在这种模式下启动的activity可以被多次实例化,即在同一个任务中可以存在多个activity的实例,每个实例都会处理一个Intent对象。如果Activity A的启动模式为standard,并且A已经启动,在A中再次启动Activity A,即调用startActivity(new Intent(this,A.class)),会在A的上面再次启动一个A的实例,即当前的桟中的状态为A-->A。

    singleTop

    如果一个以singleTop模式启动的activity的实例已经存在于任务桟的桟顶,那么再启动这个Activity时,不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例的onNewIntent()方法将Intent对象传递到这个实例中。举例来说,如果A的启动模式为singleTop,并且A的一个实例已经存在于栈顶中,那么再调用startActivity(new Intent(this,A.class))启动A时,不会再次创建A的实例,而是重用原来的实例,并且调用原来实例的onNewIntent()方法。这是任务桟中还是这有一个A的实例。

    如果以singleTop模式启动的activity的一个实例已经存在与任务桟中,但是不在桟顶,那么它的行为和standard模式相同,也会创建多个实例。

    singleTask

    谷歌的官方文档上称,如果一个activity的启动模式为singleTask,那么系统总会在一个新任务的最底部(root)启动这个activity,并且被这个activity启动的其他activity会和该activity同时存在于这个新任务中。如果系统中已经存在这样的一个activity则会重用这个实例,并且调用他的onNewIntent()方法。即,这样的一个activity在系统中只会存在一个实例。

    其实官方文档中的这种说法并不准确,启动模式为singleTask的activity并不会总是开启一个新的任务。详情请参考 解开Android应用程序组件Activity的"singleTask"之谜,在本文后面也会通过示例来进行验证。

    singleInstance

    总是在新的任务中开启,并且这个新的任务中有且只有这一个实例,也就是说被该实例启动的其他activity会自动运行于另一个任务中。当再次启动该activity的实例时,会重用已存在的任务和实例。并且会调用这个实例的onNewIntent()方法,将Intent实例传递到该实例中。和singleTask相同,同一时刻在系统中只会存在一个这样的Activity实例。

     

    12、NDK是什么

    NDK:NativeDevelopment Kit

     AndroidNDK是一个让开发人员在Android应用中嵌入使用本地代码编写的组件的工具集。

    Android应用运行在Dalvik虚拟机中。NDK允许开发人员使用本地代码语言(例如C和C++)实现应用的部分功能。这样以代码重用的形式能够给某类应用提供方便,而且在某些情况下能提高运行速度(感谢老婆的帮助)。

     

    13、请解释下Android程序运行时权限与文件系统权限的区别

    答:运行时权限Dalvik( android授权) 
        文件系统 linux 内核授权

    14、横竖屏切换时候activity的生命周期?

    1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次 

    2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次 

    3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

    15、如何设定Android应用为系统应用

    1 将自己的应用方到android源代码的packages/apps/目录下,添加Android.mk文件 
    2 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。 
    3 修改Android.mk文件,加入LOCAL_CERTIFICATE:= platform这一行 
    4 使用mm命令来编译,生成的apk就有同system一样的权限了。 
    5 在android根目录下用make snod重新生成system.img 
    6 启动emulator运行下应用看看是否好了。 

    16、如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?

    可以将dictionary.db文件复制到Eclipse Android工程中的res aw目录中。所有在res aw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将dictionary.db文件复制到res aw目录中 
    17.如何将打开res aw目录中的数据库文件? 
    解答:在Android中不能直接打开resaw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res aw目录中资源的 InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。

    18、线程中wait和sleep的区别

    答:wait释放线程锁,sleep不是线程锁,wait不占用系统资源sleep占用资源

    19、两种方法注册broadcaseReceiver,及区别。

    答:动态注册和静态注册一个BroadcastReceiver的区别:

    动态注册较静态注册灵活。实验证明:当静态注册一个BroadcastReceiver时,不论应用程序是启动与否。都可以接受对应的广播。

    动态注册的时候,如果不执行unregisterReceiver();方法取消注册,跟静态是一样的。但是如果执行该方法,当执行过以后,就不能接受广播了。

    20、在android中,请简述jni的调用过程。

    1)安装和下载Cygwin,下载 Android NDK
    2)在ndk项目中JNI接口的设计
    3)使用C/C++实现本地方法
    4)JNI生成动态链接库.so文件
    5)将动态链接库复制到java工程,在java工程中调用,运行java工程即可
    21、简述Android应用程序结构是哪些?

    Android应用程序结构是:
    Linux Kernel(Linux内核)、

    Libraries(系统运行库或者是c/c++核心库)、

    Application Framework(开发框架包)、

    Applications (核心应用程序)
    22、请继承SQLiteOpenHelper实现:

    1).创建一个版本为1的“diaryOpenHelper.db”的数据库,
    2).同时创建一个 “diary” 表(包含一个_id主键并自增长,topic字符型100
    长度, content字符型1000长度)
    3).在数据库版本变化时请删除diary表,并重新创建出diary表。

    publicclass DBHelper  extendsSQLiteOpenHelper{

    public final static String DATABASENAME ="diaryOpenHelper.db";
    public final static int DATABASEVERSION =1;

    //创建数据库
    public DBHelper(Context context,Stringname,CursorFactory factory,int version)
    {
    super(context, DATABASENAME, factory, DATABASEVERSION);
    }
    //创建表等机构性文件
    public void onCreate(SQLiteDatabase db)
    {
    String sql ="create tablediary"+
    "("+
    "_idinteger primary key autoincrement,"+
    "topicvarchar(100),"+
    "contentvarchar(1000)"+
    ")";
    db.execSQL(sql);
    }
    //若数据库版本有更新,则调用此方法
    public void onUpgrade(SQLiteDatabasedb,int oldVersion,int newVersion)
    {

    String sql = "drop table ifexists diary";
    db.execSQL(sql);
    this.onCreate(db);
    }
    }

    23、页面上现有ProgressBar控件progressBar,请用书写线程以10秒的的时间完成其进度显示工作。
    publicclass ProgressBarStu extends Activity {

    private ProgressBar progressBar = null;
    protected void onCreate(BundlesavedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.progressbar);
    //从这到下是关键
    progressBar = (ProgressBar)findViewById(R.id.progressBar);

    Thread thread = new Thread(newRunnable() {

    @Override
    public void run() {
    int progressBarMax =progressBar.getMax();
    try {
    while(progressBarMax!=progressBar.getProgress())
    {

    intstepProgress = progressBarMax/10;
    intcurrentprogress = progressBar.getProgress();
    progressBar.setProgress(currentprogress+stepProgress);
    Thread.sleep(1000);
    }

    } catch(InterruptedException e) {
    // TODO Auto-generatedcatch block
    e.printStackTrace();
    }

    }
    });

    thread.start();

    //关键结束
    }

    }
    24、请描述下Activity的生命周期。

    必调用的三个方法:onCreate() --<onStart() --< onResume(),用AAA表示
    (1)父Activity启动子Activity,子Actvity退出,父Activity调用顺序如下
    AAA --< onResume () --< onPause() --< onStop() --<onRestart()--< onStart(),onResume() …
    (2)用户点击Home,Actvity调用顺序如下
    AAA --< onResume () --< onPause() --< onStop() -- Maybe--<onDestroy() – Maybe
    (3)调用finish(), Activity调用顺序如下
    AAA --< onPause() --< onStop() --< onDestroy()
    (4)在Activity上显示dialog,Activity调用顺序如下
    AAA
    (5)在父Activity上显示透明的或非全屏的activity,Activity调用顺序如下
    AAA --< onResume () --< onPause()
    (6)设备进入睡眠状态,Activity调用顺序如下
    AAA --< onFreeze() --< onPause()
    25、如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?

    在oncreate中写如下取得保存的状态:

    1.  if (savedInstanceState != null  

    2.              && savedInstanceState.getInt("currentposition") != 0) {  

    3.    

    4.          videoView.seekTo(savedInstanceState.getInt("currentposition"));  

    5.      }  

    重写这个方法保存状态

    6.  protected void onSaveInstanceState(Bundle outState) {  

    7.      // TODO Auto-generated method stub  

    8.      outState.putInt("currentposition", videoView.getCurrentPosition());  

    9.      Log.v("tag", "onSaveInstanceState");  

    10.     super.onSaveInstanceState(outState);  

    11. }   


    当你的程序中某一个Activity A在运行时,主动或被动地运行另一个新的Activity B,这个时候A会执行onSaveInstanceState()。B完成以后又会来找A,这个时候就有两种情况:一是A被回收,二是A没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上了参数savedInstanceState;而没被收回的就直接执行onResume(),跳过onCreate()了。 
    26、如何将一个Activity设置成窗口的样式。

    在AndroidManifest.xml 中定义Activity的地方一句话android:theme="@android:style/Theme.Dialog"或android:theme="@android:style/Theme.Translucent"就变成半透明的
    27、如何退出Activity?如何安全退出已调用多个Activity的Application?

    对于单一Activity的应用来说,退出很简单,直接finish()即可。
    当然,也可以用killProcess()和System.exit()这样的方法。

    28、请介绍下ContentProvider是如何实现数据共享的。

    创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Contentprovider中,前提是有相同数据类型并且有写入Contentprovider的权限。

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

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

    Handler有两个主要的用途:

    (1)确定在将来的某个时间点执行一个或者一些Message和Runnable对象。

    (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对象包含一些信息,Handler的hanlerMessage(Message)会处理这些Message.当然,handlerMessage(Message)必须由Handler的子类来重写。这是编程人员需要作的事。

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

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


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


    MessageQueue简介:
    这是一个包含message列表的底层类。Looper负责分发这些message。Messages并不是直接加到一个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() {
                  publicvoidhandleMessage(Message msg) {
                      // processincomingmessages here
                  }
              };
              
              Looper.loop();
          }
      }
    30、系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。

    通过直接发送Uri把参数带过去,或者通过manifest里的intentfilter里的data属性

    31、什么是ANR如何避免它?

    ANR:ApplicationNotResponding,五秒 

    在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时,Android就会显示ANR对话框了: 

    对输入事件(如按键、触摸屏事件)的响应超过5秒 

    意向接受器(intentReceiver)超过10秒钟仍未执行完毕 

    Android应用程序完全运行在一个独立的线程中(例如main)。这就意味着,任何在主线程中运行的,需要消耗大量时间的操作都会引发ANR。因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intentbroadcast)。 

    因此,任何运行在主线程中的方法,都要尽可能的只做少量的工作。特别是活动生命周期中的重要方法如onCreate()和 onResume()等更应如此。潜在的比较耗时的操作,如访问网络和数据库;或者是开销很大的计算,比如改变位图的大小,需要在一个单独的子线程中完成(或者是使用异步请求,如数据库操作)。但这并不意味着你的主线程需要进入阻塞状态已等待子线程结束 -- 也不需要调用Therad.wait()或者Thread.sleep()方法。取而代之的是,主线程为子线程提供一个句柄(Handler),让子线程在即将结束的时候调用它(xing:可以参看Snake的例子,这种方法与以前我们所接触的有所不同)。使用这种方法涉及你的应用程序,能够保证你的程序对输入保持良好的响应,从而避免因为输入事件超过5秒钟不被处理而产生的ANR。这种实践需要应用到所有显示用户界面的线程,因为他们都面临着同样的超时问题

  • 相关阅读:
    uva 408 Uniform Generator
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 不同单词个数统计
    Java实现 蓝桥杯VIP 算法提高 不同单词个数统计
  • 原文地址:https://www.cnblogs.com/ruishuang208/p/4056226.html
Copyright © 2011-2022 走看看