Android 搜索框架使用详解

目录
  • 搜索框架简介
  • 使用搜索框架实现搜索功能
    • 可搜索配置
    • 搜索页面
    • 使用SearchView
    • 使用搜索弹窗
    • 搜索弹窗对Activity生命周期的影响
    • 附加额外的参数
    • 语音搜索
  • 搜索记录
    • 创建SearchRecentSuggestionsProvider
    • 修改可搜索配置
    • 在搜索页面中保存查询
    • 清除搜索历史
  • 示例

搜索框架简介

App中搜索功能是必不可少的,搜索功能可以帮助用户快速获取想要的信息。对此,Android提供了一个搜索框架,本文介绍如何通过搜索框架实现搜索功能。

Android 搜索框架提供了搜索弹窗和搜索控件两种使用方式。

  • 搜索弹窗:系统控制的弹窗,激活后显示在页面顶部,输入的内容提交后会通过Intent传递到指定的搜索Activity中处理,可以添加搜索建议。
  • 搜索控件(SearchView):系统实现的搜索控件,可以放在任意位置(可以与Toolbar结合使用),默认情况下与EditText类似,需要自己添加监听处理用户输入的数据,通过配置可以达到与搜索弹窗一致的行为。

使用搜索框架实现搜索功能

可搜索配置

在res/xml目录下创建searchable.xml(必须用此命名),如下:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint"
    android:label="@string/app_name" />

android:label是此配置文件必须配置的属性,通常配置为App的名字,android:hint配置用户未输入内容时的提示文案,官方建议格式为“搜索${content or product}”

更多可搜索配置包含的语法和用法可以看官方文档

搜索页面

配置一个单独的Activity用于显示搜索内容,用户可能会在搜索完一个内容后立刻搜索下一个内容,所以建议把搜索页面设置为SingleTop,避免重复创建搜索页面。

AndroidManifest中配置搜索页面,如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        ...
        >
        <activity
            android:name=".search.SearchActivity"
            android:exported="false"
            android:launchMode="singleTop">
            <meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable" />
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Activity中处理搜索数据,代码如下:

class SearchActivity : AppCompatActivity() {
    private lateinit var binding: LayoutSearchActivityBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.layout_search_activity)
        // 当搜索页面第一次打开时,获取搜索内容
        getQueryKey(intent)
    }
    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        // 更新Intent数据
        setIntent(intent)
        // 当搜索页面多次打开,并仍在栈顶时,获取搜索内容
        getQueryKey(intent)
    }
    private fun getQueryKey(intent: Intent?) {
        intent?.run {
            if (Intent.ACTION_SEARCH == action) {
                // 用户输入的内容
                val queryKey = getStringExtra(SearchManager.QUERY) ?: ""
                if (queryKey.isNotEmpty()) {
                    doSearch(queryKey)
                }
            }
        }
    }
    private fun doSearch(queryKey: String) {
        // 根据用户输入内容执行搜索操作
    }
}

使用SearchView

SearchView可以放在页面的任意位置,本文与Toolbar结合使用,如何在Toolbar中创建菜单项在上一篇文章中介绍过,此处省略。要使SearchView与搜索弹窗保持一致的行为需要在代码中进行配置,如下:

class SearchActivity : AppCompatActivity() {
    private lateinit var binding: LayoutSearchActivityBinding
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.example_seach_menu, menu)
        menu?.run {
            val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
            val searchView = findItem(R.id.action_search).actionView as SearchView
            //设置搜索配置
            searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName))
        }
        return true
    }
    ...
}

使用搜索弹窗

Activity中使用搜索弹窗,如果Activity已经配置为搜索页面则无需额外配置,否则需要在AndroidManifest中添加配置,如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        ...
        >
        <activity
            android:name=".search.SearchExampleActivity">
            <!--为当前页面指定搜索页面-->
            <!--如果所有页面都使用搜索弹窗,则将此meta-data移到applicaion标签下-->
            <meta-data
                android:name="android.app.default_searchable"
                android:value=".search.SearchActivity" />
        </activity>
    </application>
</manifest>

Activity中通过onSearchRequested方法来调用搜索弹窗,如下:

class SearchExampleActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: LayoutSearchExampleActivityBinding = DataBindingUtil.setContentView(this, R.layout.layout_search_example_activity)
        binding.btnSearchDialog.setOnClickListener { onSearchRequested() }
    }
}

搜索弹窗对Activity生命周期的影响

搜索弹窗的显示隐藏,不会像其他弹窗一样触发ActivityonPauseonResume方法。如果在搜索弹窗显示隐藏的同时需要对其他功能进行处理,可以通过onSearchRequestedOnDismissListener来实现,代码如下:

class SearchExampleActivity : AppCompatActivity() {
    override fun onSearchRequested(): Boolean {
        // 搜索弹窗显示,可以在此处理其他功能
        return super.onSearchRequested()
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: LayoutSearchExampleActivityBinding = DataBindingUtil.setContentView(this, R.layout.layout_search_example_activity)
        binding.btnSearchDialog.setOnClickListener { onSearchRequested() }
        val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
        searchManager.setOnDismissListener {
            // 搜索弹窗隐藏,可以在此处理其他功能
        }
    }
}

附加额外的参数

使用搜索弹窗时,如果需要附加额外的参数用于优化搜索查询的过程,例如用户的性别、年龄等,可以通过如下代码实现:

// 配置额外参数
class SearchExampleActivity : AppCompatActivity() {
    override fun onSearchRequested(): Boolean {
        val appData = Bundle()
        appData.putString("gender", "male")
        appData.putInt("age", 24)
        startSearch(null, false, appData, false)
        // 返回true表示已经发起了查询
        return true
    }
    ...
}
// 在搜素页面中获取额外参数
class SearchActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        intent?.run {
            if (Intent.ACTION_SEARCH == action) {
                // 用户输入的内容
                val queryKey = getStringExtra(SearchManager.QUERY) ?: ""
                // 额外参数
                val appData = getBundleExtra(SearchManager.APP_DATA)
                appData?.run {
                    val gender = getString("gender") ?: ""
                    val age = getInt("age")
                }
            }
        }
    }
}

语音搜索

语音搜索让用户无需输入内容就可进行搜索,要开启语音搜索,需要在searchable.xml增加配置,如下:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint"
    android:label="@string/app_name"
    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" />

语音搜索必须配置showVoiceSearchButton用于显示语音搜索按钮,配置launchRecognizer指定语音搜索按钮启动一个语音识别程序用于识别语音转录为文本并发送至搜索页面。

更多语音搜索配置包含的语法和用法可以看官方文档

注意,语音识别后的文本会直接发送至搜索页面,无法更改,需要进行完备的测试确保语音搜索功能适合你的App。

搜索记录

用户执行过搜索后,可以将搜索的内容保存下来,下次要搜索相同的内容时,输入部分文字后就会显示匹配的搜索记录。

要实现此功能,需要完成下列步骤:

创建SearchRecentSuggestionsProvider

自定义RecentSearchProvider继承SearchRecentSuggestionsProvider,代码如下:

class RecentSearchProvider : SearchRecentSuggestionsProvider() {
    companion object {
        // 授权方的名称(建议设置为文件提供者的完整名称)
        const val AUTHORITY = "com.chenyihong.exampledemo.search.RecentSearchProvider"
        // 数据库模式
        // 必须配置 DATABASE_MODE_QUERIES
        // 可选配置 DATABASE_MODE_2LINES,为搜索记录提供第二行文本,可用于作为详情补充
        const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES
    }
    init {
        // 设置搜索授权方的名称与数据库模式
        setupSuggestions(AUTHORITY, MODE)
    }
}

AndroidManifest中配置Provider,如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        ...
        >
        <!--android:authorities的值与RecentSearchProvider中的AUTHORITY一致-->
        <provider
            android:name=".search.RecentSearchProvider"
            android:authorities="com.chenyihong.exampledemo.search.RecentSearchProvider"
            android:exported="false" />
    </application>
</manifest>

修改可搜索配置

searchable.xml增加配置,如下:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint"
    android:label="@string/app_name"
    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"
    android:searchSuggestAuthority="com.chenyihong.exampledemo.search.RecentSearchProvider"
    android:searchSuggestSelection=" ?"/>

android:searchSuggestAuthority 的值与RecentSearchProvider中的AUTHORITY保持一致。android:searchSuggestSelection的值必须为" ?",该值为数据库选择参数的占位符,自动由用户输入的内容替换。

在搜索页面中保存查询

获取到用户输入的数据时保存,代码如下:

class SearchActivity : BaseGestureDetectorActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        intent?.run {
            if (Intent.ACTION_SEARCH == action) {
                val queryKey = getStringExtra(SearchManager.QUERY) ?: ""
                if (queryKey.isNotEmpty()) {
                    // 第一个参数为用户输入的内容
                    // 第二个参数为第二行文本,可为null,仅当RecentSearchProvider.MODE为DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES时有效。
                    SearchRecentSuggestions(this@SearchActivity, RecentSearchProvider.AUTHORITY, RecentSearchProvider.MODE)
                        .saveRecentQuery(queryKey, "history $queryKey")
                }
            }
        }
    }
}

清除搜索历史

为了保护用户的隐私,官方的建议是App必须提供清除搜索记录的功能。请求搜索记录可以通过如下代码实现:

class SearchActivity : BaseGestureDetectorActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        SearchRecentSuggestions(this, RecentSearchProvider.AUTHORITY, RecentSearchProvider.MODE)
            .clearHistory()
    }
}

示例

整合之后做了个示例Demo,代码如下:

// 可搜索配置
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint"
    android:label="@string/app_name"
    android:searchSuggestAuthority="com.chenyihong.exampledemo.search.RecentSearchProvider"
    android:searchSuggestSelection=" ?"
    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" />
// 清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        ...
        >
        <activity
            android:name=".search.SearchExampleActivity"
            android:screenOrientation="portrait">
            <!--为当前页面指定搜索页面-->
            <meta-data
                android:name="android.app.default_searchable"
                android:value=".search.SearchActivity" />
        </activity>
        <activity
            android:name=".search.SearchActivity"
            android:exported="false"
            android:launchMode="singleTop"
            android:parentActivityName="com.chenyihong.exampledemo.search.SearchExampleActivity"
            android:screenOrientation="portrait">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="com.chenyihong.exampledemo.search.SearchExampleActivity" />
            <meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable" />
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
        </activity>
        <provider
            android:name=".search.RecentSearchProvider"
            android:authorities="com.chenyihong.exampledemo.search.RecentSearchProvider"
            android:exported="false" />
    </application>
</manifest>
// 示例Activity
class SearchExampleActivity : BaseGestureDetectorActivity() {
    override fun onSearchRequested(): Boolean {
        val appData = Bundle()
        appData.putString("gender", "male")
        appData.putInt("age", 24)
        startSearch(null, false, appData, false)
        return true
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: LayoutSearchExampleActivityBinding = DataBindingUtil.setContentView(this, R.layout.layout_search_example_activity)
        binding.btnSearchView.setOnClickListener { startActivity(Intent(this, SearchActivity::class.java)) }
        binding.btnSearchDialog.setOnClickListener { onSearchRequested() }
        val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
        searchManager.setOnDismissListener {
            runOnUiThread { Toast.makeText(this, "Search Dialog dismiss", Toast.LENGTH_SHORT).show() }
        }
    }
}
class SearchActivity : BaseGestureDetectorActivity() {
    private lateinit var binding: LayoutSearchActivityBinding
    private val textDataAdapter = TextDataAdapter()
    private val originData = ArrayList<String>()
    private var lastQueryValue = ""
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.example_seach_menu, menu)
        menu?.run {
            val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
            val searchView = findItem(R.id.action_search).actionView as SearchView
            searchView.setOnCloseListener {
                textDataAdapter.setNewData(originData)
                false
            }
            searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName))
            if (lastQueryValue.isNotEmpty()) {
                searchView.setQuery(lastQueryValue, false)
            }
        }
        return true
    }
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        if (item.itemId == R.id.action_clear_search_histor) {
            SearchRecentSuggestions(this, RecentSearchProvider.AUTHORITY, RecentSearchProvider.MODE)
                .clearHistory()
        }
        return super.onOptionsItemSelected(item)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.layout_search_activity)
        setSupportActionBar(binding.toolbar)
        supportActionBar?.run {
            title = "SearchExample"
            setHomeAsUpIndicator(R.drawable.icon_back)
            setDisplayHomeAsUpEnabled(true)
        }
        binding.rvContent.adapter = textDataAdapter
        originData.add("test data qwertyuiop")
        originData.add("test data asdfghjkl")
        originData.add("test data zxcvbnm")
        originData.add("test data 123456789")
        originData.add("test data /.,?-+")
        textDataAdapter.setNewData(originData)
        // 获取搜索内容
        getQueryKey(intent, false)
    }
    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        // 更新Intent数据
        setIntent(intent)
        // 获取搜索内容
        getQueryKey(intent, true)
    }
    private fun getQueryKey(intent: Intent?, newIntent: Boolean) {
        intent?.run {
            if (Intent.ACTION_SEARCH == action) {
                val queryKey = getStringExtra(SearchManager.QUERY) ?: ""
                if (queryKey.isNotEmpty()) {
                    SearchRecentSuggestions(this@SearchActivity, RecentSearchProvider.AUTHORITY, RecentSearchProvider.MODE)
                        .saveRecentQuery(queryKey, "history $queryKey")
                    if (!newIntent) {
                        lastQueryValue = queryKey
                    }
                    val appData = getBundleExtra(SearchManager.APP_DATA)
                    doSearch(queryKey, appData)
                }
            }
        }
    }
    private fun doSearch(queryKey: String, appData: Bundle?) {
        appData?.run {
            val gender = getString("gender") ?: ""
            val age = getInt("age")
        }
        val filterData = originData.filter { it.contains(queryKey) } as ArrayList<String>
        textDataAdapter.setNewData(filterData)
    }
}

ExampleDemo github

ExampleDemo gitee

效果如图:

以上就是Android 搜索框架使用详解的详细内容,更多关于Android 搜索框架使用的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android开发中Signal背后的bug与解决

    目录 背景 出现SIGABRT的原因 SIGSEGV被捕获但是调用jni无法进行 小结 背景 熟悉我的老朋友可能都知道,之前为了应对crash与anr,开源过一个“民间偏方”的库Signal,用于解决在发生crash或者anr时进行应用的重启,从而最大程度减少其坏影响. 在维护的过程中,发生过这样一件趣事,就是有位朋友发现在遇到信号为SIGSEGV时,再调用信号处理函数的时候 void SigFunc(int sig_num, siginfo *info, void *ptr) { // 这里判

  • Google 开发Android MVP架构Demo深入解析

    目录 1.什么是MVP? 2.Google官方的MVP 3.V1.1 My MVP V1 4.V1.2 My MVP V2 1.什么是MVP? Google在2016年推出了官方的Android MVP架构Demo,本文主要分析一下官方的MVP Demo,并且借由自己的一些经验,提出一些学习过程中,遇到的问题和自己的改进.封装措施. MVP架构已经推出很多年了,现在已经非常普及了,我在这里就不过多介绍,简单的说,它分为以下三个层次: Model:数据模型层,主要用来数据处理,获取数据: View

  • Android ApplicationContext接口深入分析

    目录 需求 实现方法 代码 调用 Application getApplicationContext() 参考 需求 Android(Kotlin)获取应用全局上下文 ApplicationContext. 希望可以在应用内任意位置获取上下文,而不是仅在 Activity 或 Service 里才能获取. ApplicationContext 是和应用全局相关的. 实现方法 自定义 MyApplication,保存自身的 Application 实例. MyApplication 配置到 And

  • Android 获取实时网速实现详解

    目录 正文 TrafficStats简介 实现获取网速 实时网速 正文 最近接到个需求,需要计算WebView加载网页时的网速.查询了一下,Android没有提供直接获取网速的Api,但是提供了获取流量的类TrafficStats.本文介绍如何使用Trafficstats来实现获取网速功能. TrafficStats简介 TrafficStats提供了一些获取设备从本次开机到目前为止传输/接收的流量的接口,如下: 方法 参数 说明 getTotalTxBytes - 获取设备本次开机到目前为止,

  • Android 使用Toolbar实现应用栏实例详解

    目录 使用Toolbar实现应用栏 应用栏功能扩展 返回 菜单 使用Toolbar实现应用栏 App中应用栏是十分常见的,通常应用栏会显示当前页面的标题,还有一些操作按钮,例如返回.搜索.扫码等.本文介绍如何通过Toolbar实现应用栏. 使用Toolbar来实现应用栏,需要在AndroidManifest中设置NoActionBar的主题,并且Activity需要继承AppCompatActivity. <?xml version="1.0" encoding="ut

  • Android Jetpack导航组件Navigation创建使用详解

    目录 引言 依赖项 创建导航图 导航宿主 导航到目的地 传递参数 NavigationUI 多模块导航 引言 导航是指支持用户导航.进入和退出应用中不同内容片段的交互.Android Jetpack 的导航组件可实现导航,无论是简单的按钮点击,还是应用栏和抽屉式导航栏等更为复杂的模式,该组件均可应对. 依赖项 def nav_version = "2.5.2" implementation "androidx.navigation:navigation-fragment-kt

  • Android O对后台Service限制详解

    目录 Service问题 什么是前台应用 前台Service和后台Service 后台Service限制 解决后台Service限制 Service问题 Service没有界面,运行于后台,它会消耗设备资源,并且可能会导致不好的用户体验,例如资源占用过多,导致设备运行不流畅.为了缓解这个问题,Android O版本(Android 8.0, API 26)对后台Service强加了一些限制.注意,只是对后台Service加了限制,前台Service不受影响. 什么是前台应用 在解释后台Servi

  • Android 控件自动贴边实现实例详解

    目录 正文 判断交互 隐藏与显示 示例 正文 最近接到个需求,需要在用户与App交互时,把SDK中之前实现过的悬浮控件贴边隐藏,结束交互后延迟一段时间再自动显示.本篇文章介绍一下实现的思路. 判断交互 用户与App交互.结束交互可以通过监听触摸事件来实现.建议使用的Activity的dispatchTouchEvent,Activity下的所有触摸事件分发时都会回调此方法,代码如下: class AutoEdgeHideActivity : BaseGestureDetectorActivity

  • Android 搜索框架使用详解

    目录 搜索框架简介 使用搜索框架实现搜索功能 可搜索配置 搜索页面 使用SearchView 使用搜索弹窗 搜索弹窗对Activity生命周期的影响 附加额外的参数 语音搜索 搜索记录 创建SearchRecentSuggestionsProvider 修改可搜索配置 在搜索页面中保存查询 清除搜索历史 示例 搜索框架简介 App中搜索功能是必不可少的,搜索功能可以帮助用户快速获取想要的信息.对此,Android提供了一个搜索框架,本文介绍如何通过搜索框架实现搜索功能. Android 搜索框架

  • Android的搜索框架实例详解

    基础知识 Android的搜索框架将代您管理的搜索对话框,您不需要自己去开发一个搜索框,不需要担心要把搜索框放什么位置,也不需要担心搜索框影响您当前的界面.所有的这些工作都由SearchManager类来为您处理(以下简称"搜索管理器"),它管理的Android搜索对话框的整个生命周期,并执行您的应用程序将发送的搜索请求,返回相应的搜索关键字. 当用户执行一个搜索,搜索管理器将使用一个专门的Intent把搜索查询的关键字传给您在配置文件中配置的处理搜索结果的Activity.从本质上讲

  • Android车载多媒体开发MediaSession框架示例详解

    目录 一.多媒体应用架构 1.1 音视频传统应用架构 1.2 MediaSession 框架 媒体会话 媒体控制器 二.MediaSession 2.1 概述 2.2 MediaBrowser 2.2.1 MediaBrowser.ConnectionCallback 2.2.2 MediaBrowser.ItemCallback 2.2.3 MediaBrowser.MediaItem 2.2.4 MediaBrowser.SubscriptionCallback 2.3 MediaContr

  • Android Google AutoService框架使用详解

    目录 AutoService的使用 关于SPI SPI示例 APT技术 AutoService源码 AutoService源码分析 一般我们用它来自动帮我们注册APT文件(全称是Annotation Process Tool,或者叫注解处理器,AbstractProcessor的实现).很多生成SPI文件的框架也是抄袭它的源码,可见它的作用还不小. APT其实就是基于SPI一个工具,是JDK留给开发者的一个在编译前处理注解的接口.APT也是SPI的一个应用.关于SPI和APT下文会详细讲到. 先

  • Android SurfaceView基础用法详解

    Android 游戏开发框架核心组件 核心组件介绍 SurfaceView 介绍 SurfaceView 介绍 SurfaceView 就是带 Surface 的 view,它是一个 View,是 View 的子类,所以和其他 View 一样,可以在屏幕上展示东西接收用户输入,具有 View 的生命周期回调函数,如 onMeasure.onLayout.onDraw.onTouchEvent 等 SurfaceView 带有独立的 Surface(独立与 window 的 surface),这可

  • Android ContentProvider基础应用详解

    目录 一.适用场景 二.概念介绍 1.ContentProvider简介 2.Uri类简介 三.使用步骤 1.首先创建一个继承自ContentProvider的类,并实现其6个方法: 2.在Manifest文件中注册这个ContentProvider: 3.在外部应用中访问它: 一.适用场景 1.ContentProvider为存储和读取数据提供了统一的接口 2. 使用ContentProvider,应用程序可以实现数据共享 3. android内置的许多数据都是使用ContentProvide

  • Android架构发展进化详解

    目录 一.MVC架构 1.概述 2.例子 二.MVP架构 1.概述 2.例子 三.MVVM架构 1.概述 2.例子 四.Clean架构 1.概述 2.例子 五.MVI架构 1.概述 2.例子 六.总结 1.从MVC架构到MVI架构 2.从clean code到clean coder 3.MVI架构之后 一.MVC架构 1.概述 MVC架构是第一个应用于Android开发的成熟架构,由Model.View.Controller三部分组成: Model:负责数据的存储及相关逻辑. View:负责界面

  • Android分包MultiDex策略详解

    1.分包背景 这里首先介绍下MultiDex的产生背景. 当Android系统安装一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt.DexOpt的执行过程是在第一次加载Dex文件的时候执行的.这个过程会生成一个ODEX文件,即Optimised Dex.执行ODex的效率会比直接执行Dex文件的效率要高很多. 但是在早期的Android系统中,DexOpt有一个问题,DexOpt会把每一个类的方法id检索起来,存在一个链表结构里面.但是这个链表的长度是用一

  • Android AOP注解Annotation详解(一)

    Android 注解Annotation 相关文章: Android AOP注解Annotation详解(一) Android AOP之注解处理解释器详解(二) Android AOP 注解详解及简单使用实例(三) Android AOP 等在Android上应用越来越广泛,例如框架ButterKnife,Dagger2,EventBus3等等,这里我自己总结了一个学习路程. - Java的注解Annotation - 注解处理解析器APT(Annotation Processing Tool)

  • Android View.onMeasure方法详解及实例

    Android View.onMeasure方法详解及实例 View在屏幕上显示出来要先经过measure(计算)和layout(布局). 1.什么时候调用onMeasure方法? 当控件的父元素正要放置该控件时调用.父元素会问子控件一个问题,"你想要用多大地方啊?",然后传入两个参数--widthMeasureSpec和heightMeasureSpec. 这两个参数指明控件可获得的空间以及关于这个空间描述的元数据. 更好的方法是你传递View的高度和宽度到setMeasuredDi

随机推荐