Android MVVM框架使用(十二)记事本功能增强:视图类型、批量删除、搜索笔记

简介: Android MVVM框架使用(十二)记事本功能增强:视图类型、批量删除、搜索笔记

前言


 在上一篇文章中完成了记事本基本功能,就是增删改查,本文对一些功能进行增强,对用户的体验就会更好。完成这一篇文章就可以实现下面的效果图

546c7151636f4b88b0353257b055adcb.gif


3cb90ed206fd4abba6a02c35da957f76.gif

f3a0dcb2eb114203ac960fad2886c2cd.gif


正文


 功能一个一个来写,首先是视图类型,默认展示列表视图,增加一个宫格视图。


一、增加宫格视图


在menu包下创建notebook_settings.xml,里面的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/item_view_type"
        android:title="宫格视图" />
</menu>


下面在NotebookActivity中新增变量

//菜单Item
    private MenuItem itemViewType;
    @Inject
    MVUtils mvUtils;

9cdfcf3b4bca4490b9f7d9d5ef8ac973.png

使用ActionBar,设置菜单。因为有两种视图:列表视图和宫格视图,所以我们可以用一个缓存去处理,在Constant中增加一个常量:


/**
     * 笔记页面视图方式
     */
    public static final String NOTEBOOK_VIEW_TYPE = "notebookViewType";


然后我们通过缓存的方式去显示哪种视图,修改代码如下图所示:


455a91ae4eca402ca79b5931317864c8.png


下面在NotebookActivity中创建菜单,代码如下:


@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.notebook_settings, menu);
        itemViewType = menu.findItem(R.id.item_view_type).setTitle(mvUtils.getInt(Constant.NOTEBOOK_VIEW_TYPE) == 1 ? "列表视图" : "宫格视图");
        return super.onCreateOptionsMenu(menu);
    }


是一个item,根据不同的类型设置不同的item标题。


然后就是菜单item点击事件,增加代码如下:


@Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        // 0 是列表视图 1 是宫格视图
        int viewType = mvUtils.getInt(Constant.NOTEBOOK_VIEW_TYPE);
        if (item.getItemId() == R.id.item_view_type) {//视图方式
            if (viewType == 0) {
                viewType = 1;
                itemViewType.setTitle("列表视图");
                binding.rvNotebook.setLayoutManager(new GridLayoutManager(context, 2));
            } else {
                viewType = 0;
                itemViewType.setTitle("宫格视图");
                binding.rvNotebook.setLayoutManager(new LinearLayoutManager(context));
            }
            mvUtils.put(Constant.NOTEBOOK_VIEW_TYPE, viewType);
        } 
        return true;
    }


最后为了使item显示出来比较好看,需要修改一下布局,修改activity_notebook.xml中,如下图所示:


92b7c1bd8e2242ab9a1425c43f771c79.png


然后在item_notebook.xml中修改布局的边距


534152599b754622898a714da0d117fd.png


下面运行一下:


546c7151636f4b88b0353257b055adcb.gif


二、批量删除


 现在虽说也有删除,是一个一个删,假如我有一天心情不好了,我有一百个笔记,一个一个删就不太友好,用户会疯狂叼程序员,什么玩意,一点都不够人性化,那么针对这一点我们也需要弄一个批量删除,这是很有必要的。那么怎么去做呢?首先要做的是UI上的变化,这是第一点。


① 菜单修改


 菜单修改,首先是增加一个批量删除的入口,目前的菜单只有一个item,用于切换列表视图,这里在notebook_settings.xml中增加一个item,如下图所示:


73240b55b7d24ae9aba875affb1cdf6b.png


然后回到NotebookActivity中,


96203ec3a4bb486b85c15abca76081a0.png


增加点击的处理,这里的点击之后就切换当前页面的模式,布局UI修改。


② UI修改


在activity_notebook.xml中增加data中的变量数据,因为需要通过xml去改变布局的图标,文字,文字颜色。


10fa3e5578ea4dd1bff9fa8ad59c45e1.png


当触发批量删除时,首先修改标题:


978e6ac5932a4b2885d55de11089fec4.png


其次隐藏掉浮动按钮:


31b58a7e4c4f4450af202a5bbe0cca88.png


最后在页面底部增加一个布局,这个布局里面是删除和多选:


<!--批量删除模式下显示的布局-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:layout_alignParentBottom="true"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:visibility="@{isBatchDeletion ? View.VISIBLE : View.GONE}">
            <TextView
                android:id="@+id/tv_delete"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:drawableTop="@mipmap/ic_delete"
                android:gravity="center"
                android:text="删除"
                android:textColor="@color/black" />
            <TextView
                android:id="@+id/tv_all_selected"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:drawableTop="@{isAllSelected ? ContextCompat.getDrawable(tvAllSelected.getContext(),R.mipmap.ic_all_selected) : ContextCompat.getDrawable(tvAllSelected.getContext(),R.mipmap.ic_all_select)}"
                android:gravity="center"
                android:text="@{isAllSelected ? `取消全选` : `全选`}"
                android:textColor="@{isAllSelected ? @color/purple_500 : @color/black}" />
        </LinearLayout>

31b58a7e4c4f4450af202a5bbe0cca88.png

图标去我的源码中拿,添加位置如下图所示:


13debad5bc214ca3901898cc600dd883.png


现在是页面修改完了,还有item的布局中也需要改动,打开item_notebook.xml,增加变量数据代码:


e6c6c3ef820f424184b0a074ad05b2a9.png


这里你会看到我把这个item的点击事件去掉了,这部分代码我将会挪到NoteActivity中,因此这里要修改一下item_notebook.xml中的代码:


<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="notebook"
            type="com.llw.mvvm.db.bean.Notebook" />
        <!--是否批量删除-->
        <variable
            name="isBatchDeletion"
            type="Boolean" />
        <!--视图,用于控制显示隐藏-->
        <import type="android.view.View" />
        <!--用于加载mipmap中的图标-->
        <import type="androidx.core.content.ContextCompat"/>
        <!--R文件-->
        <import type="com.llw.mvvm.R"/>
    </data>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/dp_4"
        android:background="@drawable/shape_bg_white_radius_12"
        android:foreground="?attr/selectableItemBackground"
        android:padding="12dp">
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_toStartOf="@+id/iv_check"
            android:ellipsize="end"
            android:singleLine="true"
            android:text="@{notebook.title}"
            android:textColor="@color/black"
            android:textSize="16sp" />
        <TextView
            android:id="@+id/tv_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tv_title"
            android:layout_marginTop="4dp"
            android:layout_toStartOf="@+id/iv_check"
            android:ellipsize="end"
            android:maxLines="3"
            android:text="@{notebook.content}"
            android:textSize="14sp" />
        <ImageView
            android:id="@+id/iv_check"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true"
            android:layout_marginStart="6dp"
            android:src="@{notebook.select ? ContextCompat.getDrawable(ivCheck.getContext(),R.mipmap.ic_selected) : ContextCompat.getDrawable(ivCheck.getContext(),R.mipmap.ic_select)}"
            android:visibility="@{isBatchDeletion ? View.VISIBLE : View.GONE}" />
    </RelativeLayout>
</layout>


还是老样子,图标去我源码里面拿。


③ 适配器修改


item布局改完了,下面是NotebookAdapter适配器。


3daa2fd33e9a43ce94ee065ea45d768b.png


这里我去掉了之前写的点击事件内部类。


④ 修改删除方法


 之前写的NotebookDao中的删除方法是删除单个笔记的,那如果要删除多个呢?这里我们改成动态参数就行了。


208e645ff3b34a0a9cbf3d22ce517d71.png


就在后面加三个点就行了,这个表示你一个笔记可以,多个笔记也行。下面修改NotebookRepository中的deleteNotebook方法的参数,


1fff96aa75d8476fa6a91a007a4c7ada.png


然后再修改NotebookViewModel中的deleteNotebook方法中的参数。


ecb6586711d34fd79b5a08f01629702b.png


⑤ 列表处理


 现在就只剩下NotebookActivity中的代码没写了,首先在NotebookActivity增加变量,代码如下:


//笔记适配器
    private NotebookAdapter notebookAdapter;
    //笔记列表
    private final List<Notebook> mList = new ArrayList<>();
    //是否为批量删除
    private boolean isBatchDeletion = false;
    //是否全选
    private boolean isAllSelected;


实现页面的点击监听。


57bb5acaeafd430e8e2bfc8d187251e5.png


控件监听


4edbe7c7677242a5a1d26aec6c47a205.png


重写onClick方法。


@Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_delete:
                break;
            case R.id.tv_all_selected:
                break;
            default:
                break;
        }
    }


这里针对页面中底部布局中的两个TextView的点击,一个用于删除,一个用于全选和取消全选。这两个按钮的处理事件先不管它,先弄别的,这里我们先修改一下onResume中的代码:


baa241b41301459980c138d20445ffa0.png


这里之前的代码,我写到一个方法里面去了,新建一个initList方法。


/**
     * 初始化列表
     */
    private void initList() {
        //适配器
        notebookAdapter = new NotebookAdapter(mList);
        //设置适配器
        binding.rvNotebook.setAdapter(notebookAdapter);
        binding.rvNotebook.setLayoutManager(mvUtils.getInt(Constant.NOTEBOOK_VIEW_TYPE) == 1 ?
                new GridLayoutManager(context, 2) : new LinearLayoutManager(context));
        //item点击事件
        notebookAdapter.setOnItemClickListener((adapter, view, position) -> {
            if (isBatchDeletion) {
                //选中设备
                mList.get(position).setSelect(!mList.get(position).isSelect());
                notebookAdapter.notifyDataSetChanged();
                //修改页面标题
                changeTitle();
            } else {
                Intent intent = new Intent(NotebookActivity.this, EditActivity.class);
                intent.putExtra("uid", mList.get(position).getUid());
                startActivity(intent);
            }
        });
    }


这里还有一个修改页面标题的方法,也就是说当你选择了笔记时会记录选择个数。


/**
     * 修改标题
     */
    private void changeTitle() {
        int selectedNum = 0;
        for (Notebook notebook : mList) {
            if (notebook.isSelect()) {
                selectedNum++;
            }
        }
        Log.e(TAG, "changeTitle: " + selectedNum);
        binding.tvTitle.setText("已选择 "+ selectedNum +" 项");
        binding.setIsAllSelected(selectedNum == mList.size());
    }


刚才的initList方法,在onCreate中调用。


5016768728404767957640050abe0e79.png


下面就是通过点击菜单的批量删除item时调用的方法,新增方法如下:


/**
     * 设置批量删除模式
     */
    private void setBatchDeletionMode() {
        //进入批量删除模式
        isBatchDeletion = !isBatchDeletion;
        //设置当前页面
        binding.setIsBatchDeletion(isBatchDeletion);
        if (!isBatchDeletion) {
            //取消所有选中
            for (Notebook notebook : mList) {
                notebook.setSelect(false);
            }
        }
        //设置适配器
        notebookAdapter.setBatchDeletion(isBatchDeletion);
        notebookAdapter.notifyDataSetChanged();
    }


 这个方法首先是改变当前的是否批量删除变量,然后设置到xml中,如果是false,则说明你退出了批量删除模式,则之前有过选中的笔记也要取消选中。最后设置适配器中的变化,再刷新适配器。方法调用的地方如下图所示:


b2304c1d9ccf43259a6f1c6a30286a79.png


因为页面会进入到批量删除模式,如果这个时候页面返回了则也调用一下这个方法。


e35bdf422cec43f38fafdb1e996f52c9.png


下面就是删除和全选/取消全选的方法要写一下了,首先是删除吧。


⑥ 删除笔记


 因为是删除多个笔记,因此我们需要弹窗提示一下用户,新增代码如下:


/**
     * 显示确认删除弹窗
     */
    private void showConfirmDelete() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this).setMessage("确定要删除所选的笔记吗?")
                .setPositiveButton("确定", (dialog, which) -> {
                    dialog.dismiss();
                    List<Notebook> notebookList = new ArrayList<>();
                    //删除所选中的笔记
                    for (Notebook notebook : mList) {
                        if (notebook.isSelect()) {
                            notebookList.add(notebook);
                        }
                    }
                    Notebook[] notebooks = notebookList.toArray(new Notebook[0]);
                    viewModel.deleteNotebook(notebooks);
                    //设置批量删除模式
                    setBatchDeletionMode();
                    //请求数据
                    viewModel.getNotebooks();
                })
                .setNegativeButton("取消", (dialog, which) -> dialog.dismiss());
        builder.create().show();
    }


 这里的方法主要就是将选择的笔记添加到列表中,然后列表再转笔记数组,数组可以作为动态参数传入到方法中。删除之后当然就要关闭这个批量删除模式,最后我们再查询一下数据库中的笔记。


⑦ 全选


/**
     * 全选/取消全选
     */
    private void allSelected() {
        isAllSelected = !isAllSelected;
        //设置适配器
        for (Notebook notebook : mList) {
            notebook.setSelect(isAllSelected);
        }
        //修改页面标题
        changeTitle();
        //设置当前页面
        binding.setIsAllSelected(isAllSelected);
        //刷新适配器
        notebookAdapter.notifyDataSetChanged();
    }


最后就是方法调用的地方:


55a297791b3842d99f1552270bf99857.png


代码基本上就写完了,你写的时候最后自己捋一捋这个逻辑,下面运行一下。


3cb90ed206fd4abba6a02c35da957f76.gif


这个批量删除就OK了,相对来说麻烦一些。


三、搜索笔记


 当笔记很多的时候,搜索就有必要了,你让我一条一条的去找,那是不存在的。那么事已至此,就开始写吧,写之前理一下思路啊,首先我们需要一个输入框,当输入内容之后显示删除按钮,点击按钮需要清除输入框内容,然后就是通过内容进行模糊搜索,目标字段是标题和内容,也就是说当你的输入内容和搜索的数据中标题和内容只要有一个可以匹配就可以。Emm…


① 输入布局


开始吧。首先在activity_notebook.xml中的data标签中增加变量,如下所示:

<!--是否显示输入布局-->
        <variable
            name="showSearchLay"
            type="Boolean" />
        <!--输入框是否有内容-->
        <variable
            name="isSearch"
            type="Boolean" />


然后增加一个搜索布局,代码如下:


<!--搜索笔记布局,有笔记时显示-->
            <LinearLayout
                android:id="@+id/lay_search"
                android:layout_width="match_parent"
                android:layout_height="46dp"
                android:background="@color/white"
                android:gravity="center_vertical"
                android:paddingStart="8dp"
                android:paddingEnd="8dp"
                android:visibility="@{showSearchLay ? View.VISIBLE : View.GONE}">
                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="36dp"
                    android:background="@drawable/shape_search_bg"
                    android:paddingStart="12dp"
                    android:paddingEnd="12dp">
                    <ImageView
                        android:layout_width="20dp"
                        android:layout_height="20dp"
                        android:layout_centerVertical="true"
                        android:src="@mipmap/ic_search" />
                    <EditText
                        android:id="@+id/et_search"
                        android:layout_width="match_parent"
                        android:layout_height="36dp"
                        android:layout_centerVertical="true"
                        android:layout_marginStart="32dp"
                        android:layout_marginEnd="32dp"
                        android:background="@null"
                        android:hint="搜索笔记"
                        android:textColor="@color/black"
                        android:textCursorDrawable="@drawable/custom_cursor"
                        android:textSize="@dimen/sp_14" />
                    <ImageView
                        android:id="@+id/iv_clear"
                        android:layout_width="20dp"
                        android:layout_height="20dp"
                        android:layout_alignParentEnd="true"
                        android:layout_centerVertical="true"
                        android:src="@mipmap/ic_clear"
                        android:visibility="@{isSearch ? View.VISIBLE : View.GONE}" />
                </RelativeLayout>
            </LinearLayout>


图标在我的源码里,这个布局的位置我需要说明一下:


6f4575c2e2dc43069ac7dc52c3e5a68f.png


这里注意一点就是这个搜索布局是在列表的上方,而不再没有数据布局的上方。


② 模糊搜索


 Room中的模糊搜索和常规的SQL语句有一点区别,首先打开NotebookDao,在里面增加如下代码:


// ||相当于+号
    @Query("SELECT * FROM notebook WHERE title LIKE '%' || :input || '%' OR content LIKE '%' || :input || '%' ")
    Flowable<List<Notebook>> searchNotebook(String input);


这里你看到where后面就是要搜索的字段条件,这里的|| 就等于 + ,or用来匹配另一个字段,这里有标题和内容两个字段。因为模糊搜索返回的数据也会是多条,因此用List包裹起来。下面就是调用的地方了,打开NotebookRepository,在里面增加如下代码:


/**
     * 搜索笔记
     */
    public MutableLiveData<List<Notebook>> searchNotebook(String input) {
        Flowable<List<Notebook>> listFlowable = BaseApplication.getDb().notebookDao().searchNotebook(input);
        CustomDisposable.addDisposable(listFlowable, notebooks -> {
            if (notebooks.size() > 0) {
                notebooksMutableLiveData.postValue(notebooks);
            } else {
                notebooksMutableLiveData.postValue(emptyList);
                failed.postValue("暂无数据");
            }
        });
        return notebooksMutableLiveData;
    }


这里的代码就没啥好说的,和之前的获取全部笔记方法类似。然后就是在NotebookViewModel中调用了,在NotibookViewModel中增加如下方法:


/**
     * 搜索笔记
     * @param input 输入内容
     */
    public void searchNotebook(String input) {
        notebooks = notebookRepository.searchNotebook(input);
        failed = notebookRepository.failed;
    }


③ 逻辑处理


 首先是处理搜索布局是否显示,没有数据并且搜索输入框没有内容的时候不显示。


网络异常,图片无法展示
|


处理页面的输入框监听:


//输入框监听
        binding.etSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }
            @Override
            public void afterTextChanged(Editable s) {
    if (s.length() > 0) {
                    binding.setIsSearch(true);
                    //搜索笔记
                    viewModel.searchNotebook(s.toString());
                } else {
                    //获取全部笔记
                    binding.setIsSearch(false);
                    viewModel.getNotebooks();
                }
            }
        });


处理清空图标的监听:


binding.ivClear.setOnClickListener(this);


点击时清空输入框内容,并且隐藏按钮。


5e52829d34724bd297cdcfcc0cfe91ad.png


鉴于onCreate中代码太多了,现在封装成initView方法。


696a5abe51cd448bbf58caf82ebda7d8.png


现在代码就写完了,运行一下看看:


f3a0dcb2eb114203ac960fad2886c2cd.gif

相关文章
|
2月前
|
供应链 物联网 区块链
未来触手可及:探索新兴技术的趋势与应用安卓开发中的自定义视图:从基础到进阶
【8月更文挑战第30天】随着科技的飞速发展,新兴技术如区块链、物联网和虚拟现实正在重塑我们的世界。本文将深入探讨这些技术的发展趋势和应用场景,带你领略未来的可能性。
|
2月前
|
物联网 区块链 vr&ar
未来已来:探索区块链、物联网与虚拟现实技术的融合与应用安卓与iOS开发中的跨平台框架选择
【8月更文挑战第30天】在科技的巨轮下,新技术不断涌现,引领着社会进步。本文将聚焦于当前最前沿的技术——区块链、物联网和虚拟现实,探讨它们各自的发展趋势及其在未来可能的应用场景。我们将从这些技术的基本定义出发,逐步深入到它们的相互作用和集成应用,最后展望它们如何共同塑造一个全新的数字生态系统。
|
16天前
|
Android开发 开发者
安卓开发中的自定义视图:从入门到精通
【9月更文挑战第19天】在安卓开发的广阔天地中,自定义视图是一块充满魔力的土地。它不仅仅是代码的堆砌,更是艺术与科技的完美结合。通过掌握自定义视图,开发者能够打破常规,创造出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战应用,一步步展示如何用代码绘出心中的蓝图。无论你是初学者还是有经验的开发者,这篇文章都将为你打开一扇通往创意和效率的大门。让我们一起探索自定义视图的秘密,将你的应用打造成一件艺术品吧!
41 10
|
17天前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
87 3
|
25天前
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
40 8
|
21天前
|
XML 编解码 Android开发
安卓开发中的自定义视图控件
【9月更文挑战第14天】在安卓开发中,自定义视图控件是一种高级技巧,它可以让开发者根据项目需求创建出独特的用户界面元素。本文将通过一个简单示例,引导你了解如何在安卓项目中实现自定义视图控件,包括创建自定义控件类、处理绘制逻辑以及响应用户交互。无论你是初学者还是有经验的开发者,这篇文章都会为你提供有价值的见解和技巧。
30 3
|
22天前
|
前端开发 Android开发 开发者
安卓应用开发中的自定义视图基础
【9月更文挑战第13天】在安卓开发的广阔天地中,自定义视图是一块神奇的画布,它允许开发者将想象力转化为用户界面的创新元素。本文将带你一探究竟,了解如何从零开始构建自定义视图,包括绘图基础、触摸事件处理,以及性能优化的实用技巧。无论你是想提升应用的视觉吸引力,还是追求更流畅的交互体验,这里都有你需要的金钥匙。
|
29天前
|
前端开发 搜索推荐 Android开发
探索安卓开发中的自定义视图##
【9月更文挑战第6天】 在安卓应用开发的世界里,自定义视图如同绘画艺术中的色彩,它们为界面设计增添了无限可能。通过掌握自定义视图的绘制技巧,开发者能够创造出既符合品牌形象又提升用户体验的独特界面元素。本文将深入浅出地介绍如何从零开始构建一个自定义视图,包括基础框架搭建、关键绘图方法实现、事件处理机制以及性能优化策略。准备好让你的安卓应用与众不同了吗?让我们开始吧! ##
|
XML Android开发 数据格式
Android记事本开发之界面设计
不得不提一下ADT自带的手机截屏很方便,就在DDMS里可以找到。 main.xml &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="v
1443 0
|
SQL 数据库 Android开发
Android记事本开发之SQLite数据库实现
package com.jk.service; /** * 完成数据库的创建和版本更新 */ import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import
1605 0
下一篇
无影云桌面