Android基础知识

Activity生命周期。
  • 启动Activity: onCreate()—>onStart()—>onResume(),Activity进入运行状态。

  • Activity退居后台: 当前Activity转到新的Activity界面或按Home键回到主屏: onPause()—>onStop(),进入停滞状态。

  • Activity返回前台: onRestart()—>onStart()—>onResume(),再次回到运行状态。

  • Activity退居后台,且系统内存不足, 系统会杀死这个后台状态的Activity(此时这个Activity引用仍然处在任务栈中,只是这个时候引用指向的对象已经为null),若再次回到这个Activity,则会走onCreate()–>onStart()—>onResume()(将重新走一次Activity的初始化生命周期)

  • 锁屏:onPause()->onStop()

  • 解锁:onStart()->onResume()

Android基础知识_第1张图片
Activity生命周期流程图

通过Acitivty的xml标签来改变任务栈的默认行为
  • singleTop : 栈顶复用模式。这种模式下,如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,所以它的启动三回调就不会执行,同时Activity的onNewIntent()方法会被回调。如果Activity已经存在但是不在栈顶,那么作用与standard模式一样。
  • singleTask: 栈内复用模式。创建这样的Activity的时候,系统会先确认它所需任务栈已经创建,否则先创建任务栈。然后放入Activity,如果栈中已经有一个Activity实例,那么这个Activity就会被调到栈顶。onNewIntent(),并且singleTask会清理在当前Activity上面的所有Activity(clear top)
  • singleInstance : 加强版的singleTask模式,这种模式的Activity只能单独位于一个任务栈内,由于栈内复用的特性,后续请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了。

Activity的堆栈管理以ActivityRecord为单位,所有的ActivityRecord都放在一个List里面。可以认为一个ActivityRecord就是一个Activity栈


Activity缓存方法

onSaveInstanceState()回调方法,一定会在Activity被回收之前调用。方法中有一个Bundle参数,putString()、putInt()等方法需要传入两个参数,一个键一个值。数据保存之后会在onCreate中恢复,onCreate也有一个Bundle类型的参数。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //这里,当Acivity第一次被创建的时候为空
        //所以我们需要判断一下
        if( savedInstanceState != null ){
            savedInstanceState.getString("anAnt");
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putString("anAnt","Android");

    }

  • onSavaInstanceState() 方法被调用的几种情况
    1.当按下HOME键时:
    因为系统不知道你按下HOME键后要运行多少其他的程序,自然也不知道Activity是否会被销毁,故系统会调用onSaveInstanceState(),让用户有机会保存某些非永久性的数据。
    2.按下多任务键,选择运行其他程序时。
    3.按下电源键锁屏时。
    4.从当前Activity中启动一个新的Activity时。
    5.屏幕方向切换时:
    在屏幕切换之前系统会销毁当前Activity,在屏幕切换之后系统又会自动地创建该Activity,所以该方法一定会被调用。

总而言之,onSaveInstanceState()的调用遵循的原则是:当系统“未经许可”销毁了你的Activity时,就会被调用。因为系统必须提供一个让你保存数据的机会。

  • 注意:
    1.布局中的每一个View默认实现了onSaveInstanceState()方法,这样的话,这个UI的任何改变都会自动地存储和在activity重新创建的时候自动地恢复。但是这种情况只有在你为这个UI提供了唯一的ID之后才起作用,如果没有提供ID,app将不会存储它的状态。
    2.由于onSaveInstanceState()方法调用的不确定性,你应该只使用这个方法去记录activity的瞬间状态(UI的状态)。不应该用这个方法去存储持久化数据。当用户离开这个activity的时候应该在onPause()方法中存储持久化数据(例如应该被存储到数据库中的数据)。
    3.onSaveInstanceState()如果被调用,这个方法会在onStop()前被触发,但系统并不保证是否在onPause()之前或者之后触发。

Fragment的生命周期以及与Activity之间的关系
Android基础知识_第2张图片

注意和Activity相比的区别:

  • onAttach() onDetach()
  • onCreateView() onDestoryView()

Intent的使用方法,可以传递哪些数据类型?

通过查询Intent/Bundle的API文档,我们可以知道,Intent/Bundle支持传递基本类型的数据和基本类型的数组数据,以及String/CharSequence类型的数据和String/CharSequence类型的数组数据。而对于其他类型的数据或数组数据则可以使对象序列化,例如实现Parcelable接口或实现Serializable接口。


为什么在Service中创建子线程而不是在Activity中?

这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。


Service的两种启动方法是?有什么区别?

1.在Context中通过public boolean bindService(Intent service, ServiceConnectionconn, int flags)方法来进行Service与Context的关联并启动,并且Service的生命周期依附于Context(不求同年同月同日生,但求同年同月同日死)。
2.通过public ComponentName startService(Intent service)方法去启动一个Service,此时Service的生命周期与启动它的Context无关。
3.要注意的是无论如何,都需要在AndroidManifest.xml里注册你的Service



广播(Broadcast Receiver)的两种动态注册和静态注册有什么区别?
  • 静态注册:在AndroidManifest.xml文件中进行注册,当App退出后,Receiver仍然可以接收到广播并且进行相应的处理。
  • 动态注册:在代码中动态注册,当App退出后,也就没办法在接受广播了。

保证Service不被杀死的几种方法

1.Service设置成START_STICKY

  • kill后会被重启(等待5秒左右),重传Intent,保持与重启前一样。

2.提升Service的优先级

  • 在AndroidManifest.xml文件中对于intent-file可以通过android:proiority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同样适用于广播
  • 【结论】目前看来,priority这个属性貌似只适用于Broadcast,对于Service来说无效。

3.onDestroy方法里重启Service

  • Service + Broadcast 方式,就是当Service执行onDestory()的时候,发送一个自定义的广播,当收到广播的时候,重新启动service。
  • 也可以直接在onDestroy()里startService
  • 【结论】当使用助手类软件或者直接在设置里强制停止应用时,App进程直接被结束,onDestroy方法都进不来,还是无法彻底保证。

4.监听系统广播判断Service状态

  • 通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活。
  • 【结论】这也能算是一种措施,不过见听多了会导致Service很混乱,不方便。

5.root之后放到System/app变成系统级应用

6.放一个像素在前台


如何判断应用被强杀

在Application中定义一个Static常量,赋值为-1,在Splash界面改为0,如果被强杀,application重新初始化,在父类Activity判断该常量的值。

应用被强杀如何解决

如果在每一个Activity的onCreate里判断是否被强杀,冗余了,封装到Activity的父类中,如果被强杀,跳转回主界面,如果没有被强杀,执行Activity的初始化操作,给主界面传递intent参数,主界面会调用onNewIntent方法,在onNewIntent跳转到欢迎页面,重新来一遍流程。

Asset目录与res目录的区别

res 目录下面有很多文件,例如 drawable,mipmap,raw 等。res 下面除了 raw 文件不会被压缩外,其余文件都会被压缩。同时 res目录下的文件可以通过R 文件访问。Asset 也是用来存储资源,但是 asset 文件内容只能通过路径或者 AssetManager 读取。

Android怎么加速启动Activity

启动应用 :Application 的构造方法,onCreate 方法中不要进行耗时操作,数据预读取(例如 init 数据) 放在异步中操作
启动普通的Activity:A 启动B 时不要在 A 的 onPause 中执行耗时操作。因为 B 的 onResume 方法必须等待 A 的 onPause 执行完成后才能运行

Android内存优化方法:ListView优化,及时关闭资源,图片缓存等等。

View和View Group的区别?自定义View的过程?
  • Android的UI界面都是由View和ViewGroup及其派生类组合而成的。其中,View是所有UI组件的基类,而 ViewGroup是容纳这些组件的容器,其本身也是从View派生出来的。View对象是Android平台中用户界面体现的基础单位。View类是它称为“widgets(工具)”的子类的基础,它们提供了诸如文本输入框和按钮之类的UI对象的完整实现。ViewGroup类同样为其被称为“Layouts(布局)”的子类奠定了基础,它们提供了象流式布局、表格布局以及相对布局之类的布局架构。

  • 如何自定义控件:
    1.自定义属性的声明和获取

    • 分析需要的自定义属性
    • 在res/values/attrs.xml定义声明
    • 在layout文件中进行使用
    • 在View的构造方法中进行获取

    2.测量onMeasure
    3.布局onLayout(ViewGroup)
    4.绘制onDraw
    5.onTouchEvent
    6.onInterceptTouchEvent(ViewGroup)
    7.状态的恢复与保存


Content的区别
  • Activity和Service以及Application的Context是不一样的,Activity继承自ContextThemeWraper.其他的继承自ContextWrapper
  • 每一个Activity和Service以及Application的Context都是一个新的ContextImpl对象
  • getApplication()用来获取Application实例的,但是这个方法只有在Activity和Service中才能调用的到。那么也许在绝大多数情况下我们都是在Activity或者Service中使用Application的,但是如果在一些其它的场景,比如BroadcastReceiver中也想获得Application的实例,这时就可以借助getApplicationContext()方法,getApplicationContext()比getApplication()方法的作用域会更广一些,任何一个Context的实例,只要调用getApplicationContext()方法都可以拿到我们的Application对象。
  • Activity在创建的时候会new一个ContextImpl对象并在attach方法中关联它,Application和Service也差不多。ContextWrapper的方法内部都是转调ContextImpl的方法
  • 创建对话框传入Application的Context是不可以的
  • 尽管Application、Activity、Service都有自己的ContextImpl,并且每个ContextImpl都有自己的mResources成员,但是由于它们的mResources成员都来自于唯一的ResourcesManager实例,所以它们看似不同的mResources其实都指向的是同一块内存
  • Context的数量等于Activity的个数 + Service的个数 + 1,这个1为Application

IntentService的使用场景与特点

IntentService是Service的子类,是一个异步的,会自动停止的服务,很好解决了传统的Service中处理完耗时操作忘记停止并销毁Service的问题
优点:

  • 一方面不需要自己去new Thread
  • 另一方面不需要考虑在什么时候关闭该Service
    onStartCommand中回调了onStart,onStart中通过mServiceHandler发送消息到该handler的handleMessage中去。最后handleMessage中回调onHandleIntent(intent)。

你可能感兴趣的:(Android基础知识)