Android Fragment 填坑

01.getActivity()空指针

  • 遇到的问题

    • 可能你遇到过getActivity()返回null,或者平时运行完好的代码,在“内存重启”之后,调用getActivity()的地方却返回null,报了空指针异常。
  • 出现的原因分析

    • 大多数情况下的原因:你在调用了getActivity()时,当前的Fragment已经onDetach()了宿主Activity。
阅读更多

Android Fragment 进阶

01.什么是内存重启

  • 安卓app有一种特殊情况,就是 app运行在后台的时候,系统资源紧张的时候导致把app的资源全部回收(杀死app的进程),这时把app再从后台返回到前台时,app会重启。这种情况下文简称为:“内存重启”。(屏幕旋转等配置变化也会造成当前Activity重启,本质与“内存重启”类似)
  • 在系统要把app回收之前,系统会把Activity的状态保存下来,Activity的FragmentManager负责把Activity中的Fragment保存起来。在“内存重启”后,Activity的恢复是从栈顶逐步恢复,Fragment会在宿主Activity的onCreate方法调用后紧接着恢复(从onAttach生命周期开始)。
阅读更多

Android Fragment 基础

01.什么是Fragment

  • 什么是Fragment
    • 可以简单的理解为,Fragment是显示在Activity中的Activity。它可以显示在Activity中,然后它也可以显示出一些内容。因为它拥有自己的生命周期,可以接受处理用户的事件,并且你可以在一个Activity中动态的添加,替换,移除不同的Fragment,因此对于信息的展示具有很大的便利性。
    • 作为 view 界面的一部分,Fragment 的存在必须依附于 FragmentActivit使用,并且与 FragmentActivit 一样,拥有自己的独立的生命周期,同时处理用户的交互动作。同一个 FragmentActivit 可以有一个或多个 Fragment 作为界面内容,同样Fragment也可以拥有多个子Fragment,并且可以动态添加、删除 Fragment,让UI的重复利用率和易修改性得以提升,同样可以用来解决部分屏幕适配问题。
阅读更多

Android BroadCastReceiver 二

01.监听网络状态变化

  • 写一个监听网络状态变化工具类

    • 首先需要一个用来监测当前网络状态的工具类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    class NetworkUtils {

    /**
    * 标记当前网络状态,分别是:移动数据、Wifi、未连接、网络状态已公布
    */
    public enum State {
    MOBILE, WIFI, UN_CONNECTED, PUBLISHED
    }

    /**
    * 为了避免因多次接收到广播反复提醒的情况而设置的标志位,用于缓存收到新的广播前的网络状态
    */
    private static State tempState;

    /**
    * 获取当前网络连接状态
    *
    * @param context Context
    * @return 网络状态
    */
    public static State getConnectState(Context context) {
    ConnectivityManager manager = (ConnectivityManager) context.
    getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = null;
    if (manager != null) {
    networkInfo = manager.getActiveNetworkInfo();
    }
    State state = State.UN_CONNECTED;
    if (networkInfo != null && networkInfo.isAvailable()) {
    if (isMobileConnected(context)) {
    state = State.MOBILE;
    } else if (isWifiConnected(context)) {
    state = State.WIFI;
    }
    }
    if (state.equals(tempState)) {
    return State.PUBLISHED;
    }
    tempState = state;
    return state;
    }

    private static boolean isMobileConnected(Context context) {
    return isConnected(context, ConnectivityManager.TYPE_MOBILE);
    }

    private static boolean isWifiConnected(Context context) {
    return isConnected(context, ConnectivityManager.TYPE_WIFI);
    }

    private static boolean isConnected(Context context, int type) {
    //getAllNetworkInfo() 在 API 23 中被弃用
    //getAllNetworks() 在 API 21 中才添加
    ConnectivityManager manager = (ConnectivityManager) context.
    getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
    NetworkInfo[] allNetworkInfo = new NetworkInfo[0];
    if (manager != null) {
    allNetworkInfo = manager.getAllNetworkInfo();
    }
    for (NetworkInfo info : allNetworkInfo) {
    if (info.getType() == type) {
    return info.isAvailable();
    }
    }
    } else {
    Network[] networks = new Network[0];
    if (manager != null) {
    networks = manager.getAllNetworks();
    }
    for (Network network : networks) {
    NetworkInfo networkInfo = manager.getNetworkInfo(network);
    if (networkInfo.getType() == type) {
    return networkInfo.isAvailable();
    }
    }
    }
    return false;
    }
    }
阅读更多

Android BroadCastReceiver 三

01.广播实现原理

  • Android中的广播使用了设计模式中的观察者模式:基于消息的发布/订阅事件模型。
    • 因此,Android将广播的发送者 和 接收者 解耦,使得系统方便集成,更易扩展
  • 模型中有3个角色:
    • 1.消息订阅者(广播接收者)
    • 2.消息发布者(广播发布者)
    • 3.消息中心(AMS,即Activity Manager Service
阅读更多

Android Activity 探坑分析

01.Activity异常生命周期

  • 虽然前面也说了这个异常的生命周期,但是还是有些疑问?
  • 异常条件会调用什么方法
    • 当非人为终止Activity时,比如系统配置发生改变时导致Activity被杀死并重新创建、资源内存不足导致低优先级的Activity被杀死,会调用 onSavaInstanceState() 来保存状态。该方法调用在onStop之前,但和onPause没有时序关系。
    • 有人会问,onSaveInstanceState()与onPause()的区别,onSaveInstanceState()适用于对临时性状态的保存,而onPause()适用于对数据的持久化保存。
阅读更多

Android BroadCastReceiver 一

01.什么是广播Broadcast

  • 在 Android 系统中,广播(Broadcast)是在组件之间传播数据的一种机制,这些组件可以位于不同的进程中,起到进程间通信的作用。
  • BroadcastReceiver 是对发送出来的Broadcast进行过滤、接受和响应的组件。首先将要发送的消息和用于过滤的信息(Action,Category)装入一个 Intent对象,然后通过调用Context.sendBroadcast()sendOrderBroadcast() 方法把 Intent 对象以广播形式发送出去。 广播发送出去后,所以已注册的 BroadcastReceiver 会检查注册时的 IntentFilter 是否与发送的 Intent 相匹配,若匹配则会调用 BroadcastReceiver 的 onReceiver() 方法
阅读更多

Android Activity 布局绘制

01.Activity布局加载简介

  • Activity是通过Window来控制界面的展示的,一个Window对象就是一个窗口对象,而每个Activity中都有一个相应的Window对象,所以说一个Activity对象也就可以说是一个窗口对象,而Window只是控制着界面布局文件的加载过程,那么界面布局文件的绘制流程是如何的呢?

02.handleResumeActivity

阅读更多

Android Activity 布局创建

01.前沿介绍

  • 大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与android中另外一个很重要的组件Service最大的不同,但是这个展示的界面的功能是Activity直接控制的么?界面的布局文件是如何加载到内存并被Activity管理的?android中的View是一个怎样的概念?加载到内存中的布局文件是如何绘制出来的?
  • 其实Activity对界面布局的管理是都是通过Window对象来实现的,Window对象,顾名思义就是一个窗口对象,而Activity从用户角度就是一个个的窗口实例,因此不难想象每个Activity中都对应着一个Window对象,而这个Window对象就是负责加载显示界面的。至于window对象是如何展示不同的界面的,那是通过定义不同的View组件实现不同的界面展示。
阅读更多

Android Activity 启动流程

01.Launcher启动开启Activity

  • 这个首先看LauncherActivity类中的onListItemClick方法

  • Launcher启动之后会将各个应用包名和icon与app的name保存起来,然后执行icon的点击事件的时候调用startActivity方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
    Intent intent = intentForPosition(position);
    startActivity(intent);
    }

    protected Intent intentForPosition(int position) {
    ActivityAdapter adapter = (ActivityAdapter) mAdapter;
    return adapter.intentForPosition(position);
    }

    public Intent intentForPosition(int position) {
    if (mActivitiesList == null) {
    return null;
    }

    Intent intent = new Intent(mIntent);
    ListItem item = mActivitiesList.get(position);
    intent.setClassName(item.packageName, item.className);
    if (item.extras != null) {
    intent.putExtras(item.extras);
    }
    return intent;
    }
阅读更多