Android基础视图5

来源:互联网 发布:陈冠希淘宝店铺 编辑:程序博客网 时间:2024/05/22 17:08

列表视图ListView

ListView是应用最广泛的数据显示视图,每个列表项都对应于一个布局文件。

ListView采用的是MVC设计模式。

 

M-Model  模特,演员,即即将演示的数据。

V-View   舞台,表演用的。即显示数据用的控件。

C-Controlor 控制者,业务逻辑实现层。

数组资源,字符串数组资源,写到strings.xml也可以写到一个单独的文件arrays.xml中都可以。

 

    <string-array name="hobbies">

        <item>唱歌</item>

        <item>跳舞</item>

        <item>旅游</item>

        <item>打游戏</item>

        <item>音乐</item>

        <item>运动</item>

    </string-array>

 

在Java中引用  R.array.hobbies

xml文件中引用 @array/hobbies

 

 

实现ListView的一般步骤:

1.在布局文件中编写代码(xml)

2.添加ListView标签

3.在Activity中编写Java代码

4.获取ListView对象

5.准备数据源

6.配置适配器

7.将适配器关联到ListView

8.添加事件监听器

注:如果直接继承ListActivity,里面内置了一个ListView对象,可以直接使用显示界面,就可以省略加布局这一步骤。

 

什么是适配器?

适配器是数据和视图间的桥梁,它负责把数据所提供的内容显示到视图所定义的外观中,android.R.xxx 是引用Android系统提供的资源,R.xxx是指引用自定义的资源。


适配器的种类

ArrayAdapter、SimpleAdapter、自定义的Adapter


SimpleAdapter,关键是构造此适配器对象。查看源代码:

 /**

     * Constructor

     *

     * @param context The context where the View associated with this SimpleAdapter is running

     * @param data A List of Maps. Each entry in the List corresponds to one row in the list. The

     *        Maps contain the data for each row, and should include all the entries specified in

     *        "from"

     * @param resource Resource identifier of a view layout that defines the views for this list

     *        item. The layout file should include at least those named views defined in "to"

     * @param from A list of column names that will be added to the Map associated with each

     *        item.

     * @param to The views that should display column in the "from" parameter. These should all be

     *        TextViews. The first N views in this list are given the values of the first N columns

     *        in the from parameter.

     */

 

    public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,

 @LayoutRes int resource, String[] from, @IdRes int[] to) {......}

 

 

ListActivity中内置了一个ListView,在界面只包含一个ListView时,可以不用单独写布局文件。

 

 

List<? extends Map<String, ?>>  data

? extends Map  ==>就是指Map及Map的子类

 

 

 

自定义Adapter:

实现自定义Adapter的步骤

1.继承BaseAdapter

2.实现getView方法

3.关联ListView


需要实现4个抽象方法:

getCount()

getItem()

getItemId()

getView()


关键是写出getView方法的实现,它返回一个View对象,就是用来显示每个数据项所需要的View对象。每显示一个数据项都要执行一次getView方法。


ListView的长按事件setOnItemLongClickListener包含着短按事件setOnItemClickListener,如果长按事件中的方法让其返回true意味着长按完全消化了该事件,不再往传递这个事件了。短事件就不会被执行。


ListView优化

我的例子中一个屏幕可以显示10个Item,当第1个Item只显示一半时,第11个Item也只显示一半,这两个View必需要被完整创建,因此,需要创建11个View对象。当第1个Item完全消失时,这个对象又以convertView对象作为参数传递给getView()方法,可以对这个对象进行重用,换掉上面的数据,让其显示第12个Item对象。

 

在getView方法中使用convertView和ViewHolder

inflate方法的耗时:convertView解决

findViewById方法的耗时:ViewHolder解决

 

View对象是重用的,数据是更新的。

 

Android的存储

掌握Android存储的种类

掌握SharedPreferences存储

掌握File内部存储、外部存储

掌握SQLite数据库存储技术


SD卡,包括内置的SD卡都是外部存储设备


案例:如何让程序自我判断是否是第一次运行?


Android存储包括:

SharedPreferences共享存储,主要保存一些简单的数据类型的键值对数据,这是Android特有的轻量级的存储对象。

File内部存储,使用IO流存储

SQLite数据库

Content Provider

Net网络服务器


SharedPreferences对象存储,是内部存储,数据作为文件保存在/data/data/包名/shared_prefs

保存数据的一般步骤

取得数据

获得SharedPreferences对象

获得SharedPreferences.Editor对象

使用putXXX方法写入数据

提交数据


Mode权限模式

Context.MODE_PRIVATE 当前进程(APP)才有读写权限       -rw-rw----     d l p s c b

Context.MODE_APPEND 当前进程有读写权限,模式内容追加

Context.MODE_WORLD_READABLE 全局可读                  rw-rw-r--

Context.MODE_WORLD_WRITEABLE全局可写                  rw-rw--w-


File内部存储

是保存的项目的数据目录下,使用IO流存储的,使用openFileOutput方法,采用是覆盖数据打开方式。

1.准备好数据

2.获取输出流对象

3.写入数据

4.关闭流对象

5.读取File

6.获取输入流对象,使用openFileInput方法

7.读取数据到byte[]数组容器

8.获取数据

9.关闭流对象

10.读写SD外部存储

11.使用IO流读写。

12.Android6.0开始要求危险权限必须要用户明确授权才可以使用。

13.需要用户开通权限。


SQLite数据库

在Android系统内置了SQLite数据库,可以直接使用。

只支持五种数据类型,Null,integer,text,real,blob


经常使用到的类

SQLiteDatabase数据库的主要操作的方法都在这个类中,SQLiteOpenHelper创建数据库、表、表结构、更新升级

 

SQLite数据库操作的基本方法

SQLiteDatabase db = this.openOrCreateDatabase("mydb",Context.MODE_PRIVATE,null);//打开或创建数据库

db.exeSQL(....);    //增、删、改操作

Cursor cursor = db.rawQuery(....);  //查询

db.close();   //关闭数据库

 

Android系统还为我们提供了一个辅助类SQLiteOpenHelper用来创建数据库、表,操作数据库。

   此类有两个抽象方法

onCreate()

创建数据库、创建表及表结构、以及生成表的原始数据

这个方法只在创建数据库时被调用

 

    public void onCreate(SQLiteDatabase db)

    {

        String sql = "create table users " +

                "(_id integer primary key autoincrement," +

                "username text unique," +

                "password text);";

        db.execSQL(sql);

    }


onUpgrade()

在版本号发现变化时才会被调用。

做升级操作

 

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

    {

        String sql = "drop table users;";

        db.execSQL(sql);

        onCreate(db);

    }

获得SQLiteDatabase对象

getReadableDatabase()

getWritableDatabase()

以上两个方法都能获得一个SQLiteDatabase对象

以上两个方法都是采用读写方式打开数据库,唯一的区别在于当存储满了的时候,getWritableDatabase打开方式会报错,并断开数据库连接;而getReadableDatabase打开方式同样也会报错,但紧接着会尝试以只读方式连接数据库,并可以读取数据。

 

 

写一数据库访问操作的工具类DaoUtils

public class DaoUtils

{

    private SQLiteDatabase db;

 

    public DaoUtils(Context context)

    {

        MyDBHelper dbHelper = new MyDBHelper(context);

        db = dbHelper.getWritableDatabase();

    }

 

    public void insert(User user)

    {

        String sql = "insert into users(username,password) values('"+user.getUsername()+"','"+user.getPassword()+"');";

        db.execSQL(sql);

    }

    public void insert(String name, String pwd)

    {

        String sql = "insert into users(username,password) values(?,?);";

        db.execSQL(sql,new Object[]{name,pwd});

    }

    public void update(String name,String pwd)

    {

        String sql = "update users set password = ? where username = ?;";

        db.execSQL(sql,new Object[]{pwd,name});

    }

    public void delete(String name)

    {

        String sql = "delete from users where username = '"+name+"';";

        db.execSQL(sql);

    }

    public User getByName(String name)

    {

        String sql = "select * from users where username = '"+name+"';";

        Cursor cursor = db.rawQuery(sql,null);

        User user = null;

        if (cursor.moveToNext())

        {

            user = new User();

            user.set_id(cursor.getInt(cursor.getColumnIndex("_id")));

            user.setUsername(cursor.getString(cursor.getColumnIndex("username")));

            user.setPassword(cursor.getString(cursor.getColumnIndex("password")));

        }

 

        return user;

    }

    public List<User> getAll()

    {

        List<User> data = new ArrayList<>();

        String sql = "select * from users;";

        Cursor cursor = db.rawQuery(sql,null);

        while (cursor.moveToNext())

        {

            User user = new User();

            user.set_id(cursor.getInt(cursor.getColumnIndex("_id")));

            user.setUsername(cursor.getString(cursor.getColumnIndex("username")));

            user.setPassword(cursor.getString(cursor.getColumnIndex("password")));

            data.add(user);

        }

 

        return data;

    }

    public boolean exists(String name)

    {

        String sql = "select * from users where username = '"+name+"';";

        Cursor cursor = db.rawQuery(sql,null);

        return cursor.moveToNext();

    }

 

    public void close()

    {

        db.close();

    }

}

 

使用工具类:

case R.id.saveDBBtn:

    String str7 = txt1.getText().toString();

    String str8 = txt2.getText().toString();

    DaoUtils dao = new DaoUtils(this);

    if (dao.exists(str7))

    {

        Toast.makeText(this,str7+" 此用户已存在!",Toast.LENGTH_LONG).show();

        dao.close();

        return;

    }

    dao.insert(str7,str8);

    Toast.makeText(this,"写入数据库成功!",Toast.LENGTH_LONG).show();

    dao.close();

    break;

case R.id.readDBBtn:

    DaoUtils dao1 = new DaoUtils(this);

    StringBuilder buf = new StringBuilder();

    List<User> data = dao1.getAll();

    for (int i=0;i<data.size();i++)

    {

        User user = data.get(i);

        buf.append(user.toString()+"\n");

    }

    displayView.setText(buf);

    break;

0 0
原创粉丝点击