首选项框架PreferenceFragment部分源代码分析

由于要改一些settings里面的bug以及之前在里面有做过勿扰模式,准备对勿扰模式做一个总结,那先分析一下settings的源代码,里面的核心应该就是android3.0
上面的首选项框架PreferenceFragment。

由于在3.0之前都是把这些东西放在PreferenceActivity的,可是3.0之后google建议把setting放在PreferenceFragment,可是PreferenceActivity也同一时候在用的,以下就此总结一下:

PreferenceActivity的作用是管理全部headers,而每个header相应一个PreferenceFragment,相应不同的设置种类界面所以我感觉PreferenceActivity偏向系统级的设置,就比方android系统的settings。对于一些简单的应用设置一个PreferenceFragment是能够搞定的。

我们自己定义一个
activity extends PreferenceActivity必须重写onBuildHeaders()这个方法,在这里载入一个xml布局显示:

@Override
	public void onBuildHeaders(List<Header> target) {
		// TODO Auto-generated method stub
		loadHeadersFromResource(R.xml.activity_headers, target);
	}

自己写一个xml文件看下。R.xml.activity_headers:

<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
    <header
        android:id="@+id/wifi"
        android:title="wifi"
        android:icon="@drawable/ic_launcher"
        android:fragment="com.example.preferencefragmenttest.WifiFragment"/>

     <header
        android:id="@+id/net"
        android:title="移动网络"
        android:icon="@drawable/ic_launcher"
        android:fragment="com.example.preferencefragmenttest.NetFragment"/>

     <header
        android:id="@+id/ee"
        android:title="打开activity"
        android:icon="@drawable/ic_launcher"
        >
        <intent android:action="android.intent.action.NEW"></intent>
</header>
</preference-headers>

每个header点击就会进入一个新的界面。有两种情况:要么是fragment要么是intent打开一个activity。先看看源代码了解这里的原理,为什么点击就会进入对应界面。找到父类PreferenceActivity有个方法:

public void onHeaderClick(Header header, int position) {
        if (header.fragment != null) {
            if (mSinglePane) {
                int titleRes = header.breadCrumbTitleRes;
                int shortTitleRes = header.breadCrumbShortTitleRes;
                if (titleRes == 0) {
                    titleRes = header.titleRes;
                    shortTitleRes = 0;
                }
                startWithFragment(header.fragment, header.fragmentArguments, null, 0,
                        titleRes, shortTitleRes);
            } else {
                switchToHeader(header);
            }
        } else if (header.intent != null) {
            startActivity(header.intent);
        }
    }

非常明显能够看出它推断了header相应fragment和activity的两种情况,打开activity这个好理解。看看fragment是怎么打开的,进入switchToHeader(),再进去switchToHeaderInner():

private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {
        getFragmentManager().popBackStack(BACK_STACK_PREFS,
                FragmentManager.POP_BACK_STACK_INCLUSIVE);
        if (!isValidFragment(fragmentName)) {
            throw new IllegalArgumentException("Invalid fragment for this activity: "
                    + fragmentName);
        }
        Fragment f = Fragment.instantiate(this, fragmentName, args);
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        transaction.replace(com.android.internal.R.id.prefs, f);
        transaction.commitAllowingStateLoss();
    }

非常明白的知道这个跳转的fragment被装载在当前的activity了。也是告诉我们不须要再new 自己的activity来装这个fragment,我们仅仅须要在header里面写好fragment的属性。

那么为啥有的header还是用intent指定activity呢。我分析是由于有些系统界面须要别的应用直接intent訪问。比方WIFI设置界面:

startActivity(new Intent( android.provider.Settings.ACTION_WIRELESS_SETTINGS)); 

那当然须要想自己再建一个activity了,接着就是PreferenceFragment的使用方法,也是自己定义fragment extends
PreferenceFragment,而且载入xml布局:

@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		addPreferencesFromResource(R.xml.wifi_preference);
	}

看一下这个布局。简单的写几个系统自带的preference:

<?

xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference
        android:key="isopen"
        android:title="wifi"
        android:defaultValue="true"/>
    <ListPreference
        android:key="list"
        android:title="声音大小"
        android:entries="@array/keys"
        android:entryValues="@array/values"/>
    <Preference
        android:key="click"
        android:title="单独的"
        />

</PreferenceScreen>

还能够在里面增加PreferenceCategory标签,作用是分块吧,中间间隔略微大一些,区分同一页面不同设置类别

<PreferenceCategory >
        <cn.com.demo.ota.MyButtonPreference
            android:key="start_install"
            android:title="@string/update_install"/>
    </PreferenceCategory>

PreferenceFragment里面有个方法onPreferenceTreeClick()能够重写。可是依照上面的布局发现此方法不起作用。看下这种方法源代码:

 /**
     * {@inheritDoc}
     */
    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
            Preference preference) {
        if (preference.getFragment() != null &&
                getActivity() instanceof OnPreferenceStartFragmentCallback) {
            return ((OnPreferenceStartFragmentCallback)getActivity()).onPreferenceStartFragment(
                    this, preference);
        }
        return false;
    }

看的出来,必需要这个被点击的preference含有相应的fragment。否则返回false点击不起作用。那么一般我们用

update_more = (Preference)findPreference("update_more");<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">

</span></span></span><pre name="code" class="java">update_more.setOnPreferenceClickListener(new OnPreferenceClickListener() {

				@Override
				public boolean onPreferenceClick(Preference preference) {

				}
			});

来设置preference的点击事件,最后一点怎么得到我们保存的数值呢?在该应用的文件夹下能够找到 包名_preference.xml的文件,里面就是我们保存的数值 调用getDefaultSharedPreferences就能够拿到这个的SharedPreferences对象从而取到数值。

当然上面说的都是最基础的使用方法。看settings的源码里面的preference都是自定义的,用listview显示不同类型的preference,并且看Settings.java的一个方法:

/**
     * Populate the activity with the top-level headers.
     */
    @Override
    public void onBuildHeaders(List<Header> headers) {
        loadHeadersFromResource(R.xml.iradar_settings_headers, headers);
        updateHeaderList(headers);
    }

在载入完xml文件后还调用了uodateHeadersList(headers)这里事实上就是一个动态更新,不同系统版本号用户权限不一样,呈现出来的设置界面也不一样。

时间: 2024-10-11 02:51:02

首选项框架PreferenceFragment部分源代码分析的相关文章

首选项框架PreferenceFragment部分源码分析

因为要改一些settings里面的bug以及之前在里面有做过勿扰模式,准备对勿扰模式做一个总结,那先分析一下settings的源码,里面的核心应该就是android3.0 上面的首选项框架PreferenceFragment.因为在3.0之前都是把这些东西放在PreferenceActivity的,但是3.0之后google建议把setting放在PreferenceFragment,但是PreferenceActivity也同时在用的,下面就此总结一下: PreferenceActivity的

转:Android preference首选项框架

详解Android首选项框架ListPreference 探索首选项框架 在 深入探讨Android的首选项框架之前,首先构想一个需要使用首选项的场景,然后分析如何实现这一场景.假设你正在编写一个应用程序,它提供了一个搜索 飞机航班的工具.而且,假设该应用程序的默认设置是根据机票价格由低到高的顺序显示航班,但用户可以将首选项设置为始终根据最少停站数或特定航线来航班. 如何实现这一场景? ListPreference 显 然,必须为用户提供UI 来查看排序选项列表.该列表将包含每个选项的单选按钮,

Android网络项目课程笔记-----系统设置_首选项框架&amp;Holo风格的设置

系统设置_首选项框架 步骤: 1) 新建Android XML 2) 修改Activity 继承PreferenceActivity 在onCreate() 方法中调用 addPreferencesFromResource(R.xml.settings); 如何在Android2.x版本中实现Holo风格的设置 使用HoloEveryWhere   2.1+ 提示:使用supportV7 使用步骤: 1) 拷贝Demo中的DemoAppliaction,并在清单中配置 根据编译报错,拷贝valu

【Android】PA4D_CH7 文件、保存状态和首选项

本章主要知识点如下: 了解Shared Preferences 接口OnSharedPreferenceChangeListener, 每当添加.移除或者修改一个特定的Shared Preference 时候可以调用一个回调函数 创建Preference Screen(首选项框架) PreferenceActivity,  适用于API Level 11 (SDK3.0) 以前(xml 配置) PreferenceFragment, 适用于API Level 11 (SKD3.0) 以后,兼容平

Android应用程序框架层和系统运行库层日志系统源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6598703 在开发Android应用程序时,少不了使用Log来监控和调试程序的执行.在上一篇文章Android日志系统驱动程序Logger源代码分析中,我们分析了驱动程序Logger的源代码,在前面的文章浅谈Android系统开发中Log的使用一文,我们也简单介绍在应用程序中使Log的方法,在这篇文章中,我们将详细介绍Android应用程序框架

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的 源代码.细心的读者会发现,这几篇文章分析的Binder接口都是基于C/C++语言来实现的,但是我们在编写应用程序都是基于Java语言的,那么,我 们如何使用Java语言来使用系统的Binder机

Hadoop源代码分析

关键字: 分布式云计算 Google的核心竞争技术是它的计算平台.Google的大牛们用了下面5篇文章,介绍了它们的计算设施. GoogleCluster:http://research.google.com/archive/googlecluster.html Chubby:http://labs.google.com/papers/chubby.html GFS:http://labs.google.com/papers/gfs.html BigTable:http://labs.googl

转:RTMPDump源代码分析

0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://.也提供 Android 版本. 最近研究了一下它内部函数调用的关系. 下面列出几个主要的函数的调用关系. RTMPDump用于下载RTMP流媒体的函数Download: 用于建立网络连接(NetConnect)的函数Connect: 用于建立网络流(NetStream)的函数 rtmpdump源代码

【实践】源代码分析工具Doxygen+Graphviz

拿到一个新项目或者一个开源框架,看源代码的方式不是先进行单步调试!最好的方式是先画出整个项目或者开源框架的类.协作.已经方法调用图,能够帮助你更快的理解框架或者项目的设计. 打包下载地址:http://download.csdn.net/detail/supermarss/8262197 1.配置工作文件夹->配置Project的基本信息->Diagrams选外部dot生成图 2.Expert选前6项基本属性->Dot中HAVE-Dot复选+DOT_PATH路径 具体步骤參考:http: