1. ListView介绍

解决大量的相似的数据显示问题

采用了MVC模式:

M: model (数据模型)

V:  view  (显示的视图)

C: controller 控制器

 

入门案例:

acitivity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/lv" />

</RelativeLayout>

MainActivity.java:

package com.itheima.listviewdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity {
    //listview的视图 V view
    private ListView lv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv = (ListView) findViewById(R.id.lv);
        //设置数据适配器 数据控制器 adapter 相当于C controller
        lv.setAdapter(new MyAdapter());
        
    }

    private class MyAdapter extends BaseAdapter{ //控制器

        /**
         * 数据集合里面一共有多少条记录
         */
        @Override
        public int getCount() {
            return 5000000;
        }
        /**
         * 返回某个指定位置的view对象
         */
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView tv = new TextView(MainActivity.this);
            tv.setTextSize(25);
            tv.setText("我是第"+position+"个被生出来的");
            System.out.println("getview --positon:"+position); //M  model 数据模型, textview
            return tv;
        }
        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }
    }
    
}

这里本来我们的MyAdapter是应该实现接口ListAdapter,但是实现接口ListAdapter要实现的方法太多,不太方便使用,于是必然衍生出更加方便的API接口,那这里就是BaseAdapter(还有其他的),我们追踪至源码,知道:BaseAdapter 是实现ListAdapter接口的。

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { ………………}

 

通常默认实现类命名:

(1)BaseXXX

(2)BasicXXX

(3)SimpleXXX

(4)DefaultXXX

 

2. 由于像GridView、ListView等这样的列表组件是采用MVC模式的,因此不能直接通过列表组件对象对数据进行增、删、改操作。但是我们可以换个思路解决这个问题:

(1)首先我们直接对数据源中数据进行增、删、改操作

(2)然后调用BaseAdapter.notifyDataSetChanged方法通知列表组件进行数据更新。在调用notifyDataSetChanged方法的时候,系统会立刻调用这个BaseAdapter.getView()方法来获取当前显示的列表项的View对象,这样就更新的列表组件中显示的数据。

 

3. 下面通过一个案例来演示这个类似ListView列表组件数据修改的过程:

案例的运行效果图如下:

Android(java)学习笔记129:对ListView等列表组件中数据进行增、删、改操作_android

 

(1)首先还是布局文件,这里有主布局文件activity_main.xml,以及其他辅助的布局文件:

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <Button
        android:id="@+id/add_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="25dp"
        android:layout_marginRight="25dp"
        android:layout_marginTop="5dp"
        android:text="添加数据" 
        android:textColor="#99ff0000">
    </Button>

    <Button
        android:id="@+id/delete_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="25dp"
        android:layout_marginRight="25dp"
        android:layout_marginTop="5dp"
        android:text="删除数据" 
        android:textColor="#99ff0000">
    </Button>

    <Button
        android:id="@+id/edit_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="25dp"
        android:layout_marginRight="25dp"
        android:layout_marginTop="5dp"
        android:text="修改数据" 
        android:textColor="#99ff0000">
    </Button>

    <Button
        android:id="@+id/query_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="25dp"
        android:layout_marginRight="25dp"
        android:layout_marginTop="5dp"
        android:text="查询数据" 
        android:textColor="#99ff0000">
    </Button>

    <ListView
        android:id="@+id/show_result"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

主布局文件效果如下:

Android(java)学习笔记129:对ListView等列表组件中数据进行增、删、改操作_android_02

input_add.xml:添加数据

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <EditText
        android:id="@+id/input_add_string"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:singleLine="true" >
    </EditText>

</LinearLayout>

 

input_delete.xml:删除数据

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <EditText
        android:id="@+id/input_delete_number"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:digits="0123456789"
        android:singleLine="true" >
    </EditText>

</LinearLayout>

 

input_edit.xml:修改数据

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="输入要修改的索引" >
    </TextView>

    <EditText
        android:id="@+id/input_edit_number"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:digits="0123456789"
        android:singleLine="true" >
    </EditText>

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="内容修改为" >
    </TextView>

    <EditText
        android:id="@+id/input_edit_string"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:singleLine="true" >
    </EditText>

</LinearLayout>

 

items.xml:列表子项目样式布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/viewspot"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:padding="6dip"
        android:textColor="#88000000"
        android:textSize="25dp" >
    </TextView>

    <ImageView
        android:id="@+id/add"
        android:layout_width="100dip"
        android:layout_height="wrap_content"
        android:padding="10dip"
        android:src="@drawable/right" >
    </ImageView>

</LinearLayout>

 

(2)主要的class文件,UpdateListViewActivity.java,如下:

package com.himi.updatelistview;

import java.util.ArrayList;
import java.util.HashMap;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
  
public class UpdateListViewActivity extends Activity {   

    private Button addBtn;   
    private Button deleteBtn;   
    private Button editBtn;   
    private Button queryBtn;   
    private ListView listview;   
    // 数组   
    private SimpleAdapter listItemAdapter;   
    private ArrayList<HashMap<String, Object>> listItem = null;   
  
    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState) {   
        super.onCreate(savedInstanceState);   
        setContentView(R.layout.activity_main);   
  
        // 获取控件   
        addBtn = (Button) findViewById(R.id.add_id);   
        deleteBtn = (Button) findViewById(R.id.delete_id);   
        editBtn = (Button) findViewById(R.id.edit_id);   
        queryBtn = (Button) findViewById(R.id.query_id);   
        listview = (ListView) findViewById(R.id.show_result);   
  
        // 初始化数据   
        init();   
  
        // 设置控件事件监听   
        addBtn.setOnClickListener(addClick);   
        deleteBtn.setOnClickListener(deleteClick);   
        editBtn.setOnClickListener(editClick);   
        queryBtn.setOnClickListener(queryClick);   
  
    }   
  
    // 添加事件响应   
    OnClickListener addClick = new OnClickListener() {   
  
        public void onClick(View v) {   
            // TODO Auto-generated method stub   
  
            // 加载输入框的布局文件   
            LayoutInflater inflater = (LayoutInflater) UpdateListViewActivity.this  
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);   
            final LinearLayout layout = (LinearLayout) inflater.inflate(   
                    R.layout.input_add, null);   
  
            // 弹出的对话框   
  
            new AlertDialog.Builder(UpdateListViewActivity.this)   
                    /* 弹出窗口的最上头文字 */  
                    .setTitle("添加一条数据")   
                    /* 设置弹出窗口的图式 */  
                    .setIcon(android.R.drawable.ic_input_add)   
                    /* 设置弹出窗口的信息 */  
                    .setMessage("请输入添加的内容")   
                    .setView(layout)   
                    .setPositiveButton("确定",   
                            new DialogInterface.OnClickListener() {   
                                public void onClick(   
                                        DialogInterface dialoginterface, int i) {   
  
                                    EditText inputStringr = (EditText) layout   
                                            .findViewById(R.id.input_add_string);   
  
                                    String str = inputStringr.getText()   
                                            .toString();   
  
                                    if (str == null || str.equals("")) {   
  
                                        Toast.makeText(getApplicationContext(),   
                                                "添加的内容不能为空", Toast.LENGTH_SHORT)   
                                                .show();   
                                    } else {   
                                        HashMap<String, Object> map = new HashMap<String, Object>();   
                                        map.put("viewspot", str);   
                                        map.put("add", R.drawable.right);   
                                        listItem.add(0, map);   
                                        // 如果在前面添加一条数据添加   
                                        // listItem.add(map);   
                                        listItemAdapter.notifyDataSetChanged();   
                                        Toast.makeText(   
                                                UpdateListViewActivity.this,   
                                                "添加的一条数据为:" + str + "",   
                                                Toast.LENGTH_SHORT).show();   
  
                                    }   
  
                                }   
                            })   
                    .setNegativeButton("取消",   
                            new DialogInterface.OnClickListener() { /* 设置跳出窗口的返回事件 */  
                                public void onClick(   
                                        DialogInterface dialoginterface, int i) {   
                                    Toast.makeText(UpdateListViewActivity.this,   
                                            "取消了删除数据", Toast.LENGTH_SHORT)   
                                            .show();   
  
                                }   
                            }).show();   
  
        }   
    };   
  
    // 删除事件响应   
    OnClickListener deleteClick = new OnClickListener() {   
  
        public void onClick(View v) {   
            // TODO Auto-generated method stub   
  
            /**  
             * listItem.clear();清空所有数据  
             *  
             * */  
  
            /*  
             * listItem.clear();  
             * listItemAdapter.notifyDataSetChanged();  
             */  
  
            // 加载输入框的布局文件   
            LayoutInflater inflater = (LayoutInflater) UpdateListViewActivity.this  
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);   
            final LinearLayout layout = (LinearLayout) inflater.inflate(   
                    R.layout.input_delete, null);   
  
            // 弹出的对话框   
  
            new AlertDialog.Builder(UpdateListViewActivity.this)   
                    /* 弹出窗口的最上头文字 */  
                    .setTitle("删除一条数据")   
                    /* 设置弹出窗口的图式 */  
                    .setIcon(android.R.drawable.ic_input_delete)   
                    /* 设置弹出窗口的信息 */  
                    .setMessage("请输入删除的索引")   
                    .setView(layout)   
                    .setPositiveButton("确定",   
                            new DialogInterface.OnClickListener() {   
                                public void onClick(   
                                        DialogInterface dialoginterface, int i) {   
  
                                    EditText inputNumber = (EditText) layout   
                                            .findViewById(R.id.input_delete_number);   
  
                                    String str = inputNumber.getText()   
                                            .toString();   
  
                                    if (str == null || str.equals("")) {   
  
                                        Toast.makeText(getApplicationContext(),   
                                                "请输入一个数字", Toast.LENGTH_SHORT)   
                                                .show();   
                                    } else {   
                                        int number = Integer.valueOf(str);   
  
                                        int size = listItem.size();   
  
                                        // 判断数字是否超出数组索引范围   
                                        if (number >= size) {   
                                            Toast.makeText(   
                                                    getApplicationContext(),   
                                                    "没有找到删除的数据索引",   
                                                    Toast.LENGTH_SHORT).show();   
  
                                        } else {   
  
                                            String value = listItem.get(number)   
                                                    .toString();   
                                            listItem.remove(number);   
                                            listItemAdapter   
                                                    .notifyDataSetChanged();   
                                            Toast.makeText(   
                                                    UpdateListViewActivity.this,   
                                                    "删除的数据为:" + value + "",   
                                                    Toast.LENGTH_SHORT).show();   
  
                                        }   
                                    }   
  
                                }   
                            })   
                    .setNegativeButton("取消",   
                            new DialogInterface.OnClickListener() { /* 设置跳出窗口的返回事件 */  
                                public void onClick(   
                                        DialogInterface dialoginterface, int i) {   
                                    Toast.makeText(UpdateListViewActivity.this,   
                                            "取消了删除数据", Toast.LENGTH_SHORT)   
                                            .show();   
  
                                }   
                            }).show();   
  
        }   
    };   
    // 修改事件响应   
    OnClickListener editClick = new OnClickListener() {   
  
        public void onClick(View v) {   
            // TODO Auto-generated method stub   
            // 加载输入框的布局文件   
            LayoutInflater inflater = (LayoutInflater) UpdateListViewActivity.this  
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);   
            final LinearLayout layout = (LinearLayout) inflater.inflate(   
                    R.layout.input_edit, null);   
  
            // 弹出的对话框   
  
            new AlertDialog.Builder(UpdateListViewActivity.this)   
                    /* 弹出窗口的最上头文字 */  
                    .setTitle("修改一条数据")   
                    /* 设置弹出窗口的图式 */  
                    .setIcon(android.R.drawable.ic_dialog_alert)   
                    /* 设置弹出窗口的信息 */  
                    .setMessage("请输入修改的索引及内容")   
                    .setView(layout)   
                    .setPositiveButton("确定",   
                            new DialogInterface.OnClickListener() {   
                                public void onClick(   
                                        DialogInterface dialoginterface, int i) {   
  
                                    EditText inputEditNumber = (EditText) layout   
                                            .findViewById(R.id.input_edit_number);   
  
                                    String numberStr = inputEditNumber   
                                            .getText().toString();   
  
                                    EditText inputEditString = (EditText) layout   
                                            .findViewById(R.id.input_edit_string);   
  
                                    String editStr = inputEditString.getText()   
                                            .toString();   
  
                                    if (numberStr == null  
                                            || numberStr.equals("")) {   
  
                                        Toast.makeText(getApplicationContext(),   
                                                "请输入要修改的索引", Toast.LENGTH_SHORT)   
                                                .show();   
                                    } else {   
                                        int number = Integer.valueOf(numberStr);   
  
                                        int size = listItem.size();   
  
                                        // 判断数字是否超出数组索引范围   
                                        if (number >= size) {   
                                            Toast.makeText(   
                                                    getApplicationContext(),   
                                                    "没有找到修改的数据索引",   
                                                    Toast.LENGTH_SHORT).show();   
  
                                        } else {   
  
                                            HashMap<String, Object> map = new HashMap<String, Object>();   
                                            map.put("viewspot", editStr);   
                                            map.put("add", R.drawable.right);   
  
                                            listItem.set(number, map);   
                                            listItemAdapter   
                                                    .notifyDataSetChanged();   
  
                                            Toast.makeText(   
                                                    UpdateListViewActivity.this,   
                                                    "数据修改为:" + editStr + "",   
                                                    Toast.LENGTH_SHORT).show();   
  
                                        }   
                                    }   
  
                                }   
                            })   
                    .setNegativeButton("取消",   
                            new DialogInterface.OnClickListener() { /* 设置跳出窗口的返回事件 */  
                                public void onClick(   
                                        DialogInterface dialoginterface, int i) {   
                                    Toast.makeText(UpdateListViewActivity.this,   
                                            "取消了修改数据", Toast.LENGTH_SHORT)   
                                            .show();   
  
                                }   
                            }).show();   
  
        }   
    };   
  
    // 查询事件响应   
    OnClickListener queryClick = new OnClickListener() {   
  
        public void onClick(View v) {   
            // TODO Auto-generated method stub   
            // 查询数据   
            listItemAdapter.notifyDataSetChanged();   
        }   
    };   
  
    // 初始化数据   
    private void init() {   
  
        listItem = new ArrayList<HashMap<String, Object>>();   
        for (int i = 0; i < 12; i++) {   
            HashMap<String, Object> map = new HashMap<String, Object>();   
            map.put("viewspot", "雪饮狂刀:" + i);   
            map.put("add", R.drawable.right);   
            listItem.add(map);   
        }   
        listItemAdapter = new SimpleAdapter(getApplicationContext(), listItem,// 数据源   
                R.layout.items, new String[] { "viewspot", "add" }, new int[] {   
                        R.id.viewspot, R.id.add });   
        listview.setAdapter(listItemAdapter);   
  
    }  
    

}  

 注意事项:

->1:Inflate()和findViewById()区分使用,以及两种之间的逻辑关系?

findViewById()只能找出当前布局中的组件,即setConentView()的那个layout里的组件.

如果你的Activity里用到别的layout,比如对话框layout,你还要设置这个layout上的其他组件的内容,你就必须用inflate()方法先将对话框的layout找出来,然后再用findViewById()找到它上面的其它组件

 

->2:对数据源的增删改查,这只是对数据的操作而已,手机上面的ListView列表视图组件必须刷新显示,需要调用到notifyDataSetChanged()方法,就可以实现对listview数据的更新。如果涉及到线程,则需要在UI的线程更新。

->3:DialogInterface.OnClickListener接口实现方法Onclick()

public abstract void onClick (DialogInterface dialog, int which)  :对话框中的按钮按下时执行的方法.

参数: dialog  发生按钮按下事件的对话框(当一个Activity有多个对话框时,利用这个参数确定特定的对话框

         which   按下的按钮(例如:BUTTON1) 或按下的条目位置

对于which参数,如下:利用which参数按下的按钮(例如:BUTTON1) 或按下的条目位置

AlertDialog.Builder builder = new AlertDialog.Builder(this);
  builder.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes",this)
.setNegativeButton("No", this);
AlertDialog alert = builder.create();
alert.show();
@Override
public void onClick(DialogInterface dialog, int which) {
  // TODO Auto-generated method stub
  Log.e("---------------", which + "");
  switch (which) {
  case -1:
   Log.i("info", "你点击的YES~");
   AndProgressActivity.this.finish();
   break;
  case -2:
   Log.i("info", "你点击的NO~");
   dialog.cancel();
   break;
  default:
   break;
  }
}