`

Curso Adapter ListView ContextMenu

阅读更多

通过CursorAdapter在ListView中的数据呈现

在上一个例子中,我们可以对SQLite中的数据库进行增删改查,将数据读到游标Cursor中,然后一一读出。在Android中可以通过CursorAdapter直接将数据映射到ListView中,如下处理:

public class Chapter22Test1 extends ListActivity{
    private SQLiteDatabase  db = null;
    private Cursor cursor = null;    

    private SimpleCursorAdapter adapter = null;

    protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
        db= (new Chapter22Db (getApplicationContext())).getWritableDatabase();    
        cursor =db.rawQuery("SELECT _id,Name,Weight from mytable ORDER BY Weight", null);
        //layout/chapter_22_test1.xml的Android XML文件定义了ListView中每个单元的排列方式,每个单元R.id.c22_name和R.id.c22_gravity都是TextView,分列左右
        adapter = new SimpleCursorAdapter(this,
                R.layout.chapter_22_test1, 
                cursor, 
                new String[]{"Name","Weight"},//游标数据的名称,实际是Table列名字
                new int[]{R.id.c22_name, R.id.c22_gravity});//对应的UI微件的id
        setListAdapter(adapter);
    }

    protected void onDestroy() {
        super.onDestroy();
        cursor.close();  //我们在onCreate()中没有关闭游标,因为需要和ListView进行数据关联,关闭curosr,会导致List无数据,故在最后释放资源
        db.close(); //断开和数据库的连接,释放相关资源
    }
}

更新数据(以增加为例)

我们要实现:通过Menu弹出菜单,有一个为增加,按之,弹出一个Dialog,可以在当中填入数据,按Dialog的确定按键,在SQLite数据库的表格mytable中加入相关的数据,并且同步ListView的显示。

第一步:建立OptionsMenu,里面有菜单“Add”,按键后,触发执行add()的操作。具体实现不在此罗嗦,可以参见Android学习笔记(八):Activity-OpenMenu和LinearLayout

第二步:在add()中,要完成弹出指定格式的Dialog,采用AlertDialog的方式,Dialog的格式在xml中给出。处理方式之前都学过,但是没有合并使用的例子,包括Dialog的格式,同ListView中自定义元素的格式一样,采用LayoutInflater。具体如下:

private void add(){
    //步骤2.1:通过LayoutInflater从Android的XML文件中生成View
    LayoutInflater inflater = LayoutInflater.from(this);
    final View addView = inflater.inflate(R.layout.add_dialgo,null);

    //步骤2.2:通过AlertDialog弹出对话框,并且在第一个button,即PositiveButton监听事件,触发操作
    new AlertDialog.Builder(this)
    .setTitle("添加框")
    .setView(addView)
    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
        //我们希望得到addView中的数据,但是这个inner class,只能获取final的值,所以之前将addView设置为final,也就是所有addView的地址是固定的,而不是动态生成。
        public void onClick(DialogInterface dialog, int which) {
            EditText nameView = (EditText)addView.findViewById(R.id.c22_name);
            EditText weigthView = (EditText)addView.findViewById(R.id.c22_weight);

            // addData是下面步骤三,实现SQLite的数据更新和ListView的显示同步add(name,weight);
            addData(nameView.getText().toString(), new Float(weigthView.getText().toString()).floatValue());
        }
    })
    .setNegativeButton("取消",null)
    .show();
}

第三步:更新数据库和同步ListView,具体如下:

    private void addData(String name ,float weight){
        /* 略去数据的判断,例如如果name一样,采用update的方式等等*/
        //步骤3.1 在数据库表格中添加数据

        ContentValues values = new ContentValues(2);
        values.put("Name",name);
        values.put("Weight",weight);
        db.insert("mytable","Name",values);
        //步骤3.2 同步ListView,更新游标的信息
        cursor.requery();
    }

异步后台同步数据

在上面的例子,貌似可以,而且的确是可以,但是在Android的API文档中,Cursor的方法requery()这样写道:This method is deprecated.Don't use this. Just request a new cursor, so you can do this asynchronously and update your list view once the new cursor comes back. 这提示我们风险的存在,如果数据量大,会导致重写读取的事件长(也就是requery()的执行时间)。虽然手机是人手操作,互动频率较低,在数据库数据少的时候,例如上面的例子,我们仍然可以安全地使用requery。但是对于具有大量数据时,我们就需要修改上面的程序。

修订的方式步骤如下:1,通过后台线程来读取数据库;2、通过更换cursor来更新ListView,具体如下:

//步骤1:通过后台线程AsyncTask来读取数据库,放入更换Cursor
private class RefreshList extends AsyncTask<Void, Void ,Cursor>{
    //步骤1.1:在后台线程中从数据库读取,返回新的游标newCursor
    protected Cursor doInBackground(Void... params) {
        Cursor newCursor =  db.rawQuery("SELECT _id,Name,Weight from mytable ORDER BY Weight", null);
        return newCursor;
    }
    //步骤1.2:线程最后执行步骤,更换adapter的游标,并奖原游标关闭,释放资源  
    protected void onPostExecute(Cursor newCursor) {
        adapter.changeCursor(newCursor);//网上看到很多问如何更新ListView的信息,采用CusorApater其实很简单,换cursor就可以
        cursor.close();
        cursor = newCursor;
    }         
}
//步骤2:取缔requrey的方式,采用后台线程更新形式
private void addData(String name ,float weight){
     ... ...
    //cursor.requery();
    new RefreshList().execute();
}

通过ContextMenu来删除ListView的数据

ContextMenu用户手指长按某个View触发的菜单,见Android 学习笔记(二七):Menu。这里通过这个例子详细展开。实现场景:用户长按某个List元素,则弹出ContextMenu,选择菜单“Delete”,按下后,弹出AlertDialog,请用户再去确定是否删除,确定后将数据从SQLite中删除,并更新ListView的显示。具体如下:





    protected void onCreate(Bundle savedInstanceState) {
        ... ... 
        //步骤1:向ListView注册Context Menu,当系统检测到用户长按某单元是,触发Context Menu弹出
        registerForContextMenu(getListView());
    }

    // 步骤2:创建ContextMenu同OptionMenu,用户长按元素后,会弹出菜单

    public void onCreateContextMenu(ContextMenu menu, View v,  ContextMenuInfo menuInfo) {
        menu.add(Menu.NONE,DELETE_ID,Menu.NONE,"Delete");
        super.onCreateContextMenu(menu, v, menuInfo);
    }

    //步骤 3: ContextMenu的触发操作,例子将触发delete()
    public boolean onContextItemSelected(MenuItem item) {
        switch(item.getItemId()){
        case DELETE_ID:
            /* 在此处,我们关键引入 AdapterView.AdapterContextMenuInfo来获取单元的信息。在有三个重要的信息。 1、id:The row id of the item for which the context menu is being displayed ,在cursorAdaptor中,实际就是表格的_id序号; 2、position 是list的元素的顺序;3、view就可以获得list中点击元素的View,通过view可以获取里面的显示的信息   */

            AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
            delete(info.id);
            return true;
        default:
            break;

        }
        return super.onContextItemSelected(item);
    }

    //步骤4: 对触发弹框,和Add的相似,确定后,更新数据库和更新ListView的显示,其中getNameById是通过id查名字的方法,上次学习已有相类的例子,不再重复。值得注意的是,为了内部类中使用,delete的参数采用来final的形式。
    private void delete(final long  rowId){
        if(rowId>0){
            new AlertDialog.Builder(this)
            .setTitle("删除" + getNameById(rowId))
            .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                      deleteData(rowId);
                }
            })
            .setNegativeButton("取消", null)
            .show();

        }
    }
    
    private void deleteData(long rowId){
        String[] str = {String.valueOf(rowId)};
        db.delete("mytable","_id=?",str);

        new RefreshList().execute();  //采用后台方式,当然也可以用crusor.requery()来处理。
    }

通过模拟器的Console进行数据库操作

通过android-sdk-linux_x86/platform-tools目录下面有adb命令,使用adb shell,可提供模拟器的console窗口。数据库文件存放的位置为/data/data/your.app.package/databases/your-db-name,进入相关的目录,可以使用#sqlite3 your-db-name,进入相关的数据库,可以在里面执行SQL语句,例如在整个例子中,通过#.schema来查看表格的格式,通过#select * from mytable;可以显示数据库的内容。

分享到:
评论

相关推荐

    Curso-CSS-SASS, Curso da Webschool.io sobre.zip

    Curso-CSS-SASS, Curso da Webschool.io sobre Curso-CSS-SASSCurso da Webschool.io sobre 。使用 Através destes recursos arquivos produzir e manter grandes CSS organiza

    curso_tour_of_heroes_api:Ruby on Rails作为API课程-源码

    英雄之旅API Ruby on Rails 6课程作为创建Heroes ...PostgreSQL(产品)运行项目的初始设置# clone the projectgit clone https://github.com/peimelo/curso_tour_of_heroes_api.git# enter the cloned directorycd ...

    Curso de Eletrônica

    【标题】"Curso de Eletrônica" 涵盖了电子学这一广泛的学科领域,旨在为学习者提供全面的电子技术知识。这个课程可能包括理论基础、实践技能以及使用多种软件和工具的训练。 在电子学的基础理论部分,学生可以...

    埃森哲2021年:Curso角钢

    【标题】:“埃森哲2021年:Curso角钢” 这个标题提及的是一个由全球知名咨询公司埃森哲(Accenture)在2021年提供的名为“Curso角钢”的课程。"Curso"在西班牙语中意为课程,而“角钢”通常指的是建筑行业中的一种...

    PyPI 官网下载 | curso-2.0.tar.gz

    《PyPI官网下载 | curso-2.0.tar.gz——深入理解Python库的发布与使用》 在Python的世界里,PyPI(Python Package Index)是最重要的软件仓库,它为全球的Python开发者提供了一个集中地,用来发布、分享和安装...

    Curso-Java-Completo:Exercíciospropostos durante o curso

    【标题】"Curso-Java-Completo:Exercíciospropostos durante o curso" 提供了一个关于Java编程的学习资源,这很可能是一个全面的Java教程,涵盖了从基础到高级的各种主题,并通过一系列的练习来强化学习者的编程...

    Curso C++_CursoC++_C++Curso_C++_

    本资源是一个以西班牙语讲解的C++编程课程,名为"Curso C++",旨在帮助学习者掌握C++这一强大的编程语言。C++是一种通用的、面向对象的编程语言,由Bjarne Stroustrup于1979年在贝尔实验室创建,作为C语言的增强版。...

    curso-tdd:Cursa de Desarrollo Para Asegurar la Calidad del软件

    Curso de desarrolloágil-4月edición :heart_decoration: :heart_decoration: :heart_decoration: :heart_decoration: :heart_decoration: 取消对任何人的照料,应将其保留下来,再将其保存到可可食品中。 从...

    curso-de-matlab-master.zip

    《MATLAB基础与实践——基于"curso-de-matlab-master.zip"的学习指南》 MATLAB,全称为“矩阵实验室”(Matrix Laboratory),是一款强大的数学计算软件,被广泛应用于科学计算、数据分析、算法开发以及图形可视化...

    Curso-Python:Curso Python

    Curso-Python Curso Python

    curso_java:Curso Java

    【标题】:“curso_java:Curso Java” 这个标题表明我们正在探讨的是一个关于Java编程的课程资源,"curso_java"可能是课程的代码库或者项目名称,而"Curso Java"直译为“Java课程”,暗示这是一个教育性的资料,...

    Curso-[removed]Curso de JS do Curso em视频

    【标题】:“Curso-[removed]Curso de JS do Curso em视频” 暗示这是一个关于JavaScript的在线课程,可能由“Curso em Vídeo”提供。这个课程可能包含一系列的视频教程,旨在帮助学习者掌握JavaScript这门编程语言...

    curso-php:curso de php do Curso Em视频

    【标题】:“curso-php:curso de php do Curso Em视频”是一个关于PHP编程语言的在线课程,由“Curso Em Video”提供。这个课程旨在教授初学者和有一定基础的学习者如何使用PHP进行网页开发和服务器端脚本。 【描述...

    primer_curso_de_cracking_crack_

    primer_curso_de_cracking_de_ricardo_narvaja_completo.

    Curso 在线 Python 基础知识库.zip

    Curso 在线 Python 基础知识库Python 基础知识数据科学学院 - Python 分析基础知识本教程是关于 Python 分析基础知识库的文章。您可以使用 Jupyter Notebooks 进行所有操作,但不要使用光标,而是要进行练习。...

    curso-de-python3-mundo-2:我从Curso emVídeo的Gustavo Guanabara教授的“ Curso de Python 3:Mundo 2”课程中学到的东西。 注意:这些是“ curso-de-python3-mundo-1”存储库的以下内容

    curso-de-python3-mundo-2 我是从Curso emVídeo的Gustavo Guanabara教授的“ Curso de Python 3:Mundo 2”课程中学到的。 注意:这些是“ curso-de-python3-mundo-1”存储库的以下内容。 截至2020年10月,此存储库...

    Curso-JS:Curso JavaScript-Curso emVídeo

    本"Curso-JS:Curso JavaScript-Curso em Vídeo"课程专注于教授JavaScript的基础知识及实际应用,帮助初学者快速掌握这一强大的脚本语言。 在HTML(超文本标记语言)的基础上,JavaScript起到了桥梁的作用,它能够...

    Curso-PHP:Curso php

    【标题】:“Curso-PHP:Curso php”是一个关于PHP编程语言的在线课程资源,旨在帮助学习者掌握PHP的基础和进阶知识。 【描述】:“光标PHP Curso PHP”可能指的是该课程聚焦于PHP编程中的“光标”概念,通常在...

    Udemy:Curso de udemy

    【标题】:“Udemy:Curso de udemy”这一标题暗示了这是一个在Udemy平台上提供的在线课程,可能涵盖了各种主题和技术。Udemy是一个知名的在线学习平台,它提供了广泛的课程,包括编程、设计、营销等多个领域。在这...

    procedimentos_Curso_Phyton_python_

    在"Phyton Curso Phyton_python_"这个教程中,我们专注于使用Python语言来开发各种应用程序。Python是一种强大的、易学的编程语言,被广泛应用于数据分析、网络爬虫、机器学习、Web开发等多个领域。本教程旨在帮助...

Global site tag (gtag.js) - Google Analytics