Theme类、进程的分类、SimpleAdapter类、ANR和FC

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38703938/article/details/84873671

Android中Theme类可以继承?

不可以

解析:我们先看一下AndroidManifest.xml文件,里面有这么一行代码

android:theme="@style/AppTheme"

即对主题样式的指定、设置,接下来进入styles.xml文件

    <style name="AppTheme1" parent="Theme.AppCompat.Light">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
    <style name="Animation" />
    <style name="Animation.Dialog">
        <item name="windowEnterAnimation">@anim/dialog_enter</item>
        <item name="windowExitAnimation">@anim/dialog_exit</item>
    </style>

这里的样式代码,可以分为两种,一种是使用parent,代表该样式来自哪里?一般在java里,我们都说继承,parent即对应父类,另一种是使用已有的style名字后直接加.来表示(这种是自定义的style),这么看来,似乎Theme类是可以继承的,我就是这样认识错的。下面我们再从用代码设置主题的方面来看一下,

直接在activity里就可以设置setTheme(); 我们点进去

    @Override
    public void setTheme(@StyleRes final int resid) {
        super.setTheme(resid);
        // Keep hold of the theme id so that we can re-set it later if needed
        mThemeId = resid;
    }

我们来看一下这个mThemeId是如何使用的(只看重点,感兴趣自己看源码)

if (Build.VERSION.SDK_INT >= 23) {
                onApplyThemeResource(getTheme(), mThemeId, false);
            } else {
                setTheme(mThemeId);
            }

这里就对6.0上下进行了不同的方法设置,我们先看6.0以上的系统

    @Override
    protected void onApplyThemeResource(Resources.Theme theme, @StyleRes int resid,
            boolean first) {
        if (mParent == null) {
            super.onApplyThemeResource(theme, resid, first);
        } else {
            try {
                theme.setTo(mParent.getTheme());
            } catch (Exception e) {
                // Empty
            }
            theme.applyStyle(resid, false);
        }

        // Get the primary color and update the TaskDescription for this activity
        TypedArray a = theme.obtainStyledAttributes(
                com.android.internal.R.styleable.ActivityTaskDescription);
        if (mTaskDescription.getPrimaryColor() == 0) {
            int colorPrimary = a.getColor(
                    com.android.internal.R.styleable.ActivityTaskDescription_colorPrimary, 0);
            if (colorPrimary != 0 && Color.alpha(colorPrimary) == 0xFF) {
                mTaskDescription.setPrimaryColor(colorPrimary);
            }
        }

        int colorBackground = a.getColor(
                com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
        if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
            mTaskDescription.setBackgroundColor(colorBackground);
        }

        final int statusBarColor = a.getColor(
                com.android.internal.R.styleable.ActivityTaskDescription_statusBarColor, 0);
        if (statusBarColor != 0) {
            mTaskDescription.setStatusBarColor(statusBarColor);
        }

        final int navigationBarColor = a.getColor(
                com.android.internal.R.styleable.ActivityTaskDescription_navigationBarColor, 0);
        if (navigationBarColor != 0) {
            mTaskDescription.setNavigationBarColor(navigationBarColor);
        }

        a.recycle();
        setTaskDescription(mTaskDescription);
    }

这里面看着是否和自定义view有点相似,大概就是一层层抠出来,像我们前面写的style有parent,点到为止,这里不是研究这个问题。6.0以下的,就直接看他的父类方法

    @Override
    public void setTheme(int resid) {
        if (mThemeResource != resid) {
            mThemeResource = resid;
            initializeTheme();
        }
    }

发现,mThemeResource的使用和6.0以上类似(不做重点),继续initializeTheme(初始化主题)

    private void initializeTheme() {
        final boolean first = mTheme == null;
        if (first) {
            mTheme = getResources().newTheme();
            final Resources.Theme theme = getBaseContext().getTheme();
            if (theme != null) {
                mTheme.setTo(theme);
            }
        }
        onApplyThemeResource(mTheme, mThemeResource, first);
    }

重点出现了,Theme是用final修饰的,很明显不能被继承。

进程的分类

前台进程

用户当前操作所必需的进程。如果一个进程满足以下任一条件,即视为前台进程:

托管用户正在交互的 Activity(已调用 Activity 的 onResume() 方法)
托管某个 Service,后者绑定到用户正在交互的 Activity
托管正在“前台”运行的 Service(服务已调用 startForeground())
托管正执行一个生命周期回调的 Service(onCreate()、onStart() 或 onDestroy())
托管正执行其 onReceive() 方法的 BroadcastReceiver
通常,在任意给定时间前台进程都为数不多。只有在内存不足以支持它们同时继续运行这一万不得已的情况下,系统才会终止它们。 此时,设备往往已达到内存分页状态,因此需要终止一些前台进程来确保用户界面正常响应。

可见进程

没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。 如果一个进程满足以下任一条件,即视为可见进程:

托管不在前台、但仍对用户可见的 Activity(已调用其 onPause() 方法)。例如,如果前台 Activity 启动了一个对话框,允许在其后显示上一 Activity,则有可能会发生这种情况。
托管绑定到可见(或前台)Activity 的 Service。
可见进程被视为是极其重要的进程,除非为了维持所有前台进程同时运行而必须终止,否则系统不会终止这些进程。

服务进程

正在运行已使用 startService() 方法启动的服务且不属于上述两个更高类别进程的进程。尽管服务进程与用户所见内容没有直接关联,但是它们通常在执行一些用户关心的操作(例如,在后台播放音乐或从网络下载数据)。因此,除非内存不足以维持所有前台进程和可见进程同时运行,否则系统会让服务进程保持运行状态。

后台进程

包含目前对用户不可见的 Activity 的进程(已调用 Activity 的 onStop() 方法)。这些进程对用户体验没有直接影响,系统可能随时终止它们,以回收内存供前台进程、可见进程或服务进程使用。 通常会有很多后台进程在运行,因此它们会保存在 LRU (最近最少使用)列表中,以确保包含用户最近查看的 Activity 的进程最后一个被终止。如果某个 Activity 正确实现了生命周期方法,并保存了其当前状态,则终止其进程不会对用户体验产生明显影响,因为当用户导航回该 Activity 时,Activity 会恢复其所有可见状态。 有关保存和恢复状态的信息,请参阅 Activity文档。

空进程

不含任何活动应用组件的进程。保留这种进程的的唯一目的是用作缓存,以缩短下次在其中运行组件所需的启动时间。 为使总体系统资源在进程缓存和底层内核缓存之间保持平衡,系统往往会终止这些进程。

SimpleAdapter类支持的绑定view类型

if (!bound) {
                    //该view是否实现checkable接口
                    if (v instanceof Checkable) {
                        if (data instanceof Boolean) {
                            ((Checkable) v).setChecked((Boolean) data);
                        //该view是否是TextView
                        } else if (v instanceof TextView) {
                            // Note: keep the instanceof TextView check at the bottom of these
                            // ifs since a lot of views are TextViews (e.g. CheckBoxes).
                            setViewText((TextView) v, text);
                        } else {
                            throw new IllegalStateException(v.getClass().getName() +
                                    " should be bound to a Boolean, not a " +
                                    (data == null ? "<unknown type>" : data.getClass()));
                        }
                    } else if (v instanceof TextView) {
                        // Note: keep the instanceof TextView check at the bottom of these
                        // ifs since a lot of views are TextViews (e.g. CheckBoxes).
                        setViewText((TextView) v, text);
                    //该view是否是ImageView
                    } else if (v instanceof ImageView) {
                        if (data instanceof Integer) {
                            setViewImage((ImageView) v, (Integer) data);
                        } else {
                            setViewImage((ImageView) v, text);
                        }
                    } else {
                        throw new IllegalStateException(v.getClass().getName() + " is not a " +
                                " view that can be bounds by this SimpleAdapter");
                    }
                }

以上源码很明显能看出来使用SimpleAdapter作为适配器时,支持三种类型的 View,而且是按照如下顺序进行匹配: 实现Checkable接口 、TextView、 ImageView,但面试或笔试的时候,问你的不一定是这么明显,比如CompoundButton是否支持?它支持是因为它实现了checkable接口还是TextView的子类?因为这是按照顺序判断的,所以CompoundButton实现了Checkable接口,所以被SimpleAdapter支持,虽然它同样可以在第二个判断里通过,但不考虑。

ANR和FC

ANR(Application Not Respone):程序无响应,有可能程序会再次响应

出现条件:1.当用户输入事件5s内没有得到响应,将弹出ANR对话框  2.广播接收者的onReceive()执行时间超过10s

FC(Force close):程序抛出异常,会强制退出

出现条件:Error 、OOM,内存溢出 、StackOverFlowError 、Runtime,比如说空指针异常

关于这两种情况如何避免,以后再说,这里主要是要说下正确理解和区分这两种情况。

猜你喜欢

转载自blog.csdn.net/weixin_38703938/article/details/84873671