Android 锦集

01:Activity生命周期?
这几乎是个老少咸宜,永远不会过时的问题,而且极有可能是第一个问题。这个问题当然没什么好讲的啦,死记硬背是没什么用的了,关键是理解。本人就曾遇到这个问题的变种问题,问onStart(),与onResume()有什么区别?如果面试官抛出这个问题,是不是有点措手不及。今天又听说有同学遭遇了更变态的问题:什么情况下Activity走了onCreat(),而不走onStart(),这简直就是脑筋急转弯嘛。
知识点链接:http://www.jianshu.com/p/c5604ccd40ea

02:什么情况下,Activity的onNewInstent()方法会执行?Activity的启动模式相关。
当此Activity的实例已经存在,并且此时的启动模式为SingleTaskSingleInstance,另外当这个实例位于栈顶,且启动模式为SingleTop时也会触发onNewInstance()方法。

03:Service生命周期?
这里要注意service有两种启动方式:startService()和bindService()
在Service的生命周期中,常用的方法有:
4个手动调用的方法

startService()    //启动服务
stopService()     //关闭服务
bindService()     //绑定服务
unbindService()   //解绑服务```
5个内部自动调用的方法

onCreat() //创建服务
onStartCommand() //开始服务
onDestroy() //销毁服务
onBind() //绑定服务
onUnbind() //解绑服务```

  • 手动调用startService()启动服务,自动调用内部方法:onCreate(),onStartCommand(),如果一个Service被startService()多次启动,那么onCreate()也只会调用一次。
  • 手动调用stopService()关闭服务,自动调用内部方法:onDestory(),如果一个Service被启动且被绑定,如果在没有解绑的前提下使用stopService()关闭服务是无法停止服务的。
  • 手动调用bindService()后,自动调用内部方法:onCreate()、onBind()。
  • 手动调用unbindService()后,自动调用内部方法:onUnbind()、onDestory()。
  • startService()和stopService()只能开启和关闭Service,无法操作Service,调用者退出后Service仍然存在;bindService()和unbindService()可以操作Service,调用者退出后,Service随着调用者销毁。

Service知识总结
Android activity和service的生命周期对比
Service服务史上最全面解析

04:IntentService深入了解?
IntentService集成与Service,用来处理异步请求。客服端可以通过startService(Intent intent)方法传递请求给IntentService。IntentService在onCreate()函数中通过HandlerThread单独开启一个线程来依次处理所有Intent请求对象所对应的任务(这样以免事务处理阻塞主线程,出现ANR异常)执行完一个Intent请求对象所对应的工作之后,如果没有新的Intent请求达到,则自动停止Service,否则执行下一个Intent请求所对应的任务。
IntentService在处理事务时,还是采用的Handler方式,创建一个名叫ServiceHandler的内部Handler,并把它直接绑定到HandlerThread所对应的子线程。ServiceHandler把处理一个intent所对应的事务都封装到叫做onHandleIntent的虚函数中;因此我们直接实现虚函数onHandleIntent,再在里面根据intent的不同进行不同的事务处理就可以了。另外,IntentService默认实现了onBind()方法,返回值为null.
使用IntentService需要实现的两个方法:

  • 构造函数
    IntentService的构造函数一定是参数为空的构造函数,然后再在其中调用super("name")这种形式的构造函数。因为Service的实例化是系统来完成的,而且系统是参数为空的构造函数来实例化Service的。
  • 实现虚函数onHandleIntent
    在里面根据intent的不同进行不同的事务处理。
    好处:处理异步请求的时间可以减少些代码的工作量,比较轻松的实现项目的需求。

IntentService实例介绍
首先是myIntentService.java

public class myIntentService extends IntentService {
    //------------------必须实现-----------------------------
    public myIntentService() {
        super("myIntentService");
        // 注意构造函数参数为空,这个字符串就是worker thread的名字
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        //根据Intent的不同进行不同的事务处理 
        String taskName = intent.getExtras().getString("taskName");  
        switch (taskName) {
        case "task1":
            Log.i("myIntentService", "do task1");
            break;
        case "task2":
            Log.i("myIntentService", "do task2");
            break;
        default:
            break;
        }       
    }
  //--------------------用于打印生命周期--------------------    
   @Override
   public void onCreate() {
     Log.i("myIntentService", "onCreate");
     super.onCreate();
   }
    
   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
      Log.i("myIntentService", "onStartCommand");
      return super.onStartCommand(intent, flags, startId);
    }
    
    @Override
    public void onDestroy() {
        Log.i("myIntentService", "onDestroy");
        super.onDestroy();
    }
}

然后记得在Manifest.xml中注册服务

<service android:name=".myIntentService">
     <intent-filter >  
         <action android:name="cn.scu.finch"/>  
     </intent-filter>     
</service>```
最后在Activity中开启服务

public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);

    //同一服务只会开启一个worker thread,
    //在onHandleIntent函数里依次处理intent请求。
    
    Intent i = new Intent("cn.scu.finch");  
    Bundle bundle = new Bundle();  
    bundle.putString("taskName", "task1");  
    i.putExtras(bundle);  
    startService(i);  
       
    Intent i2 = new Intent("cn.scu.finch");  
    Bundle bundle2 = new Bundle();  
    bundle2.putString("taskName", "task2");  
    i2.putExtras(bundle2);  
    startService(i2); 
    
    startService(i);  //多次启动
}

}```
运行结果:

总结:IntentService在onCreate()函数中通过HandlerThread单独开启一个线程来依次处理所有Intent请求对象所对应的任务。通过onStartCommand()传递给服务intent被依次插入到工作队列中。工作队列又把intent逐个发送给onHandleIntent()。

注意:它只有一个工作线程,名字就是构造函数的那个字符串,也就是"myIntentService",我们知道多次开启service,只会调用一次onCreate()方法(创建一个工作线程),多次onStartCommand()方法(用于传入intent通过工作队列再发给onHandleIntent函数做处理)。

05:IntentService与Service的区别
Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,不建议在Service中编写耗时的逻辑和操作,否则会引起ANR。
IntentService它创建了一个独立的工作线程来处理所有的通过onStartCommand()传递给服务的intents(把intent插入到工作队列中)。通过工作队列把intent逐个发送到onHandleIntent()。不需要主动调用stopSelft()来结束服务。因为,所有的intent被处理完毕之后,系统会自动关闭服务。
默认实现的onBind(),返回null。

06:理解Activity,View,Window三者关系
首先用一个比喻来解释三者之间的关系:Activity像一个工匠(控制单元),Windows像窗户(承载模型),View像窗花(显示视图),LayoutInflater像剪刀,Xml配置像剪窗花的图纸。下面介绍:
1.Activity构造的时候会初始化一个Windows,准确的说是PhoneWindow
2.这个PhoneWindow有一个“ViewRoot”,这个“ViewRoot”是一个View或者ViewGroup,是最具初始化的根视图。
3.“ViewRoot”通过addView方法来一个个的添加View。比如TextView,Button等
4.这些View的事件监听,是由WindowManagerService来接受消息,并且回调Activity函数。比如:onClickListener,onKeyDown等

07:Fragment能否不依赖于Activity存在?简析一下Fragment的栈管理。
Fragment不能独立存在的,它必须嵌入到activity中,而且Fragment的生命周期直接受所在的activity的影响。

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();```
transaction只是记录了从一个状态到另一个状态的变化过程,既比如从FragmentA替换到FragmentB的过程,当通过函数transaction.addToBackStack(null)将这个事务添加到回退栈,则会记录这个事务的状态变化过程,如从FragmentA——>FragmentB,当用户点击手机回退键时,因为transaction的状态变化过程被保存,则可以将事务的变化过程还原,既将FragmentB——>FragmentA.
**添加到回退栈的函数:transaction.addToBackStack(null);**
[参考文章: http://blog.csdn.net/u011026329/article/details/47903177](http://blog.csdn.net/u011026329/article/details/47903177)

**08:对于同一个Service,在被start启动之后还能不能被bind?**
是可以的,Service服务基本上分为两种形式:
**启动**
当应用组件(如Activity)通过调用startService()启动服务时,服务既处于“启动”状态。一旦启动,服务既可在后台无限期运行,即使启动服务的组件已被销毁也不会受到影响。已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。例如,它可以通过网络下载或上传文件。操作完成后,服务会自行停止运行。
**绑定**
当应用组件通过bindService()方法绑定到服务时,服务既处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务器进行交互、发送请求、获取结果,甚至是利用进程间通信(IPC) 跨进程执行这些操作。仅当与另一个应用组件绑定时,绑定服务才会运行。多个组件可以同时绑定到该服务,但全部取消绑定后,该服务既会被销毁。
**虽然本文档是分开概括讨论这两种服务的,但是您的服务可以同时以这两种方式运行,也就是说,它既可以是启动服务(以无限期运行),也允许绑定。问题只是在于您是否实现一组回调方法:onStartCommand()(允许组件启动服务)和onBind()(允许绑定服务)。**

**09:Android中动画**
Android中动画分别有:**帧动画、补间动画、属性动画(Android3.0以后)**
**帧动画**
帧动画是最容易实现的一种动画,这种动画更多的依赖于完善的UI资源,他的原理就是讲一张张单独的图片连贯的进行播放(类似于与动画片的制作过程),从视觉上产生一种动画的效果;有些类似于某些软件制作gif动画的方式。有些代码中,我们还会看到```android:oneshot="false"```,这个oneshot的含义就是动画执行一次(true)还是循环执行多次。
定义代码如下:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/a_0"
android:duration="100" />
<item
android:drawable="@drawable/a_1"
android:duration="100" />
<item
android:drawable="@drawable/a_2"
android:duration="100" />
</animation-list>```
补间动画
补间动画又可以分为四种形式,分别是:alpha(淡入淡出)、translate(位移)、scale(缩放大小)、rotate(旋转)。
补间动画的实现,一般采用xml文件的形式;代码会更容易书写和阅读,同时也更容易复用。Interpolator主要作用是可以控制动画的变化速率,就是动画进行的快慢节奏。pivot决定了当前动画执行的参考位置。
代码如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:shareInterpolator=["true" | "false"] >
    <alpha
        android:fromAlpha="float"
        android:toAlpha="float" />
    <scale
        android:fromXScale="float"
        android:toXScale="float"
        android:fromYScale="float"
        android:toYScale="float"
        android:pivotX="float"
        android:pivotY="float" />
    <translate
        android:fromXDelta="float"
        android:toXDelta="float"
        android:fromYDelta="float"
        android:toYDelta="float" />
    <rotate
        android:fromDegrees="float"
        android:toDegrees="float"
        android:pivotX="float"
        android:pivotY="float" />
    <set>
        ...
    </set>
</set>

属性动画
属性动画,顾名思义它是对于对象属性的动画。因此,所有补间动画的内容,都可以通过属性动画实现。属性动画的运行机制是不断地进行操作来实现的,而初始值和结束值之间的动画过度就是由ValueAnimator这个类负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式以及对动画设置监听器等。

10:消息推送的方式

  • 方案1:使用极光、友盟、信鸽、个推等第三方推送平台(优点:方便省事,有较为完善的功能解决方案)
  • 方案2:使用XMPP协议(Openfire + Spark + Smack)
    简介:基于XML协议的通讯协议,前身是Jabber,目前已由IETF国际标准化组织完成了标准化工作。
    优点:协议成熟、强大、可扩展性强、目前主要应用到许多聊天系统中,且已有开源的Java版的开发实例androidpn。
    缺点:协议比较复杂、冗余(基于XML)、费流量、费电,部署硬件成本高。
  • 方案3:使用MQTT协议(更多信息见:http://mqtt.org/
    简介:轻量级、基于代理的“发布/订阅”模式的消息传输协议。
    优点:协议简洁、小巧、可扩展性强、省流量、省电,目前已经应用到企业领域(参考:http://mqtt.org/software),且已有C++版的服务端组件rsmb
    缺点:够成熟、实现较复杂、服务端组件rsmb不开源,部署硬件成本较高。
  • 方案4:使用HTTP轮循方式
    简介:定时向HTTP服务器接口(Web Service API)获取最新的消息。
    优点:实现简单、可控制强,部署硬件成本低。
    缺点:实时性差。

11:Android的数据存储

  • 使用SharedPreferences存储数据;它是Android提供的用来存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中。只能在同一个包内使用,不能再不同的包之间使用。
  • 文件存储数据;文件存储方式是一种比较常用的方法,在Android中读取和写入文件的方法,与Java中实现的I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来实读取设备上的文件。
  • SQLite数据库存储数据;SQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库。
  • 使用ContentProvider存储数据;主要用于应用程序之间进行数据交换,从而能够让其他的应用保存或读取此ContentProvider的各种数据类型。
  • 网络存储数据;通过网络上提供给我们的存储空间来上传(存储)和下载(获取)我们存储在网络空间中的数据信息。

12:Android ANR是什么?如何避免它?
在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框就称为:应用程序无响应(ANR:Application Not Responding)对话框。
用户可以选择让程序继续进行,但是,人们在使用应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要。这样,系统才不会显示ANR给用户。不同的组件发生ANR异常的时间,也是不一样的,如:主线程(Activity,Service)需要5秒,BroadCastReceiver需要10秒。
解决方案:将所有耗时操作,比如:访问网络、Socket通信、查询大量SQL语句、复杂逻辑计算等都放在子线程中去完成,然后通过handler.sendMessage()、runUIThread()、AsyncTask()等方式更新UI。无论如何都要确保用户界面操作的流畅度。如果耗时操作需要让用户等待,那么最好在UI界面上给用户显示进度条。

13:Android 自定义View的绘制流程
1.自定义View的属性
2.在View的构造方法中获取我们自定义的属性
[3.重写onMesure()方法]
4.重写onDraw()方法
注意:3用[]标出来,所以说3,不一定是必须的,当然了大部分的情况下还是需要重写的。
鸿洋大神--自定义View文章汇总

14:Android 自定义View的事件分发机制
Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
Android事件分发机制完全解析,带你从源码的角度彻底理解(下)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容