2.4.9 ListView Data Update Issues
Category Android Basic Tutorial
Introduction:
>
We have already learned some basic usage of ListView, but you might have noticed that our data is static and predefined. In real-world development, data is often dynamic and changes, such as adding, deleting, or modifying entries. The list should update accordingly. This section will discuss how to update ListView data, including full updates and updating individual items. Let's get started!
1. First, let's write a normal demo
>
Alright, let's start with a normal demo and then we'll adjust it gradually:
Entity class: Data.java:
/**
* Created by Jay on 2015/9/21 0021.
*/
public class Data {
private int imgId;
private String content;
public Data() {}
public Data(int imgId, String content) {
this.imgId = imgId;
this.content = content;
}
public int getImgId() {
return imgId;
}
public String getContent() {
return content;
}
public void setImgId(int imgId) {
this.imgId = imgId;
}
public void setContent(String content) {
this.content = content;
}
}
Activity layout and list item layout:
activity_main.xml:
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:id="@+id/list_one"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
item_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/img_icon"
android:layout_width="56dp"
android:layout_height="56dp"/>
<TextView
android:id="@+id/txt_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginLeft="10dp"
android:textSize="18sp" />
</LinearLayout>
Custom BaseAdapter implementation: MyAdapter.java:
/**
* Created by Jay on 2015/9/21 0021.
*/
public class MyAdapter extends BaseAdapter {
private Context mContext;
private LinkedList<Data> mData;
public MyAdapter() {}
public MyAdapter(LinkedList<Data> mData, Context mContext) {
this.mData = mData;
this.mContext = mContext;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list,parent,false);
holder = new ViewHolder();
holder.img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
holder.txt_content = (TextView) convertView.findViewById(R.id.txt_content);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.img_icon.setImageResource(mData.get(position).getImgId());
holder.txt_content.setText(mData.get(position).getContent());
return convertView;
}
private class ViewHolder{
ImageView img_icon;
TextView txt_content;
}
}
MainActivity.java implementation:
public class MainActivity extends AppCompatActivity {
private ListView list_one;
private MyAdapter mAdapter = null;
private List<Data> mData = null;
private Context mContext = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = MainActivity.this;
bindViews();
mData = new LinkedList<Data>();
mAdapter = new MyAdapter((LinkedList<Data>) mData,mContext);
list_one.setAdapter(mAdapter);
}
private void bindViews(){
list_one = (ListView) findViewById(R.id.list_one);
}
}
When you run it, you'll notice that the page has no data, just a blank screen, which isn't a good user experience. You can use the setEmptyView(View) method of ListView to display a view when there's no data. Note that dynamically added views don't work with this method; the view must be added in the layout file where the ListView is. Also, the view set by setEmptyView doesn't show up initially. For example, to display a "No data" TextView when there's no data, use the following code:
<TextView
android:id="@+id/txt_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="15pt"
android:textColor="#000000"/>
txt_empty = (TextView) findViewById(R.id.txt_empty);
txt_empty.setText("No data available~");
list_one.setEmptyView(txt_empty);
Alternatively, you can define a layout the same size and position as the ListView, set android:visibility="gone"
, and in the Java code, check the size of the mData
collection. If it's zero, show the layout; hide it when there's data.
2. Adding a Record
Let's add a button to add a record each time it's pressed.
Running effect:
Code implementation
Define a method in our custom BaseAdapter:
public void add(Data data) {
if (mData == null) {
mData = new LinkedList<>();
}
mData.add(data);
notifyDataSetChanged();
}
mData.add(data);
notifyDataSetChanged();
Then add a button to the layout and set up the event, the code is as follows:
private Button btn_add;
btn_add = (Button) findViewById(R.id.btn_add);
btn_add.setOnClickListener(this);
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_add:
mAdapter.add(new Data(R.mipmap.ic_icon_qitao,"给猪哥跪了~~~ x " + flag));
flag++;
break;
}
}
Hehe, it's done, adding data is that simple~ If you want to insert into a specific position, you can do that too. We'll add another method in our Adapter class:
// Add an element at a specific position
public void add(int position, Data data){
if (mData == null) {
mData = new LinkedList<>();
}
mData.add(position, data);
notifyDataSetChanged();
}
Then add a button and write an event:
private Button btn_add2;
btn_add2 = (Button) findViewById(R.id.btn_add2);
btn_add2.setOnClickListener(this);
case R.id.btn_add2:
// Position starts from 0
mAdapter.add(4, new Data(R.mipmap.ic_icon_qitao,"给猪哥跪了~~~ x " + flag));
break;
Running Effect Diagram:
You can see that our ninth item has been inserted into the fifth position~
3. Deleting an Item
Similarly, we write two methods, one to delete an object directly and one to delete based on the cursor:
public void remove(Data data) {
if(mData != null) {
mData.remove(data);
}
notifyDataSetChanged();
}
public void remove(int position) {
if(mData != null) {
mData.remove(position);
}
notifyDataSetChanged();
}
Then add two Buttons and call these two methods:
case R.id.btn_remove:
mAdapter.remove(mData_5);
break;
case R.id.btn_remove2:
mAdapter.remove(2);
break;
Running Effect Diagram:
From the diagram, we can see that the fifth item has been removed, and clicking the cursor to delete data always removes the third item!
4. Removing All Records:
This is even simpler, just call the clear method! The method code is as follows:
public void clear() {
if(mData != null) {
mData.clear();
}
notifyDataSetChanged();
}
5. Updating a Record
You might have noticed that after modifying the data, the notifyDataSetChanged() method is called. Initially, I thought:
notifyDataSetChanged() would redraw all items displayed on the interface, which would affect UI performance, especially if the data volume is large. But changing one item would redraw all items, which is definitely not reasonable. So, I used a naive method to modify the value of a control in an Item. I wrote this code in Java:
private void updateListItem(int position, Data mData){
int visiblePosition = list_one.getFirstVisiblePosition();
View v = list_one.getChildAt(position - visiblePosition);
ImageView img = (ImageView) v.findViewById(R.id.img_icon);
TextView tv = (TextView) v.findViewById(R.id.txt_content);
img.setImageResource(mData.getImgId());
tv.setText(mData.getContent());
}
Later, after discussing with friends in the group, I realized I was wrong:
The notifyDataSetChanged() method checks whether a redraw is necessary. If the current item does not need to be redrawn, it won't be. If the state of an Item changes, it will cause the View to be redrawn, but not all Items, just the one whose state has changed! So we can directly use the notifyDataSetChange() method, and knowing an extra method like the above is fine too~
Code Download:
Summary:
Good, this section has covered the implementation of data updates in ListView. Of course, not just ListView, other Adapter-based controls can also call these methods to update data. That's all for now, thank you.
-1.0 Android Basic Entry Tutorial
-1.0.1 2015 Latest Android Basic Entry Tutorial Table of Contents
-1.1 Background and System Architecture Analysis
-1.2 Development Environment Setup
-1.2.1 Using Eclipse + ADT + SDK to Develop Android APP
-1.2.2 Using Android Studio to Develop Android APP
-1.3 Solving SDK Update Issues
-1.4 Genymotion Emulator Installation
-1.5.1 Git Tutorial for Basic Local Repository Operations
-1.5.2 Git: Using GitHub to Build Remote Repository
-1.6 How to Play with the 9(Nine Sisters) Image
-1.7 Interface Prototype Design
-1.8 Project Related Analysis (Various Files, Resource Access)
-1.9 Android Program Signing and Packaging
-1.11 Decompiling APK to Obtain Code & Resources
-2.1 Concepts of View and ViewGroup
-2.2.1 LinearLayout (Linear Layout)
-2.2.2 RelativeLayout (Relative Layout)
-2.2.3 TableLayout (Table Layout)
-2.2.4 FrameLayout (Frame Layout)
-2.2.5 GridLayout (Grid Layout)
-2.2.6 AbsoluteLayout (Absolute Layout)
-2.3.1 TextView (Text Box) Detailed Explanation
-2.3.2 EditText (Input Box) Detailed Explanation
-2.3.5.RadioButton (Radio Button) & Checkbox (Checkbox)
-2.3.6 ToggleButton and Switch
-2.3.7 ProgressBar (Progress Bar)
-2.3.9 RatingBar (Star Rating Bar)
-2.4.1 ScrollView (Scroll Bar)
-2.4.2 Date & Time Components (Part 1)
-2.4.3 Date & Time Components (Part 2)
-2.4.5 Simple Usage of ListView
-2.4.6 BaseAdapter Optimization
-2.4.8 Solving ListView Checkbox Misalignment Issue
- 2.4.9 ListView Data Update Issue ``` -2.5.0 Building a Reusable Custom BaseAdapter
-2.5.1 Implementing Multiple Layouts for ListView Items
-2.5.2 Basic Usage of GridView (Grid View)
-2.5.3 Basic Usage of Spinner (Dropdown List)
-2.5.4 Basic Usage of AutoCompleteTextView (Auto-complete Text Field)
-2.5.5 Basic Usage of ExpandableListView (Collapsible List)
-2.5.6 Basic Usage of ViewFlipper (Flip View)
-2.5.8 Detailed Explanation of Notification (Status Bar Notification)
-2.5.9 Detailed Explanation of AlertDialog (Dialog Box)
-2.6.0 Basic Usage of Other Common Dialogs
-2.6.1 Basic Usage of PopupWindow (Floating Box)
-2.6.3 Simple Usage of ViewPager
-2.6.4 Simple Usage of DrawerLayout (Official Side Sliding Menu)
-3.1.1 Event Handling Mechanism Based on Listeners
-3.2 Event Handling Mechanism Based on Callbacks
-3.3 Analysis of Handler Message Passing Mechanism
-3.4 TouchListener vs OnTouchEvent + Multi-touch
-3.5 Listening for Content Changes in EditText
-3.6 Responding to System Setting Events (Configuration Class)
-3.7 AsyncTask Asynchronous Task
-4.1.1 Introduction to Activity
-4.1.2 Getting Started with Activity
-4.2.1 Introduction to Service
-4.3.1 Introduction to BroadcastReceiver
-4.3.2 In-depth BroadcastReceiver
-4.4.1 Introduction to ContentProvider
-4.4.2 Further Exploration of ContentProvider — Document Provider
-4.5.2 Passing Complex Data with Intent
-5.1 Basic Overview of Fragment
-5.2.1 Fragment Example Detailed — Bottom Navigation Bar Implementation (Method 1)
-5.2.2 Fragment Example Detailed — Bottom Navigation Bar Implementation (Method 2)
-5.2.3 Fragment Example Detailed — Bottom Navigation Bar Implementation (Method 3)
-5.2.4 Fragment Example Detailed — Bottom Navigation Bar + ViewPager Swipe to Switch Pages
-5.2.5 Fragment Example Detailed — Simple Implementation of News (Shopping) App List Fragment
-6.1 Data Storage and Access — File Storage and Reading
-6.2 Data Storage and Access — SharedPreferences for Saving User Preferences
-6.3.1 Data Storage and Access — Introduction to SQLite Database
-6.3.2 Data Storage and Access — Further Exploration of SQLite Database
-7.1.1 Android Network Programming and Learning HTTP Protocol
-7.1.2 Learning Android HTTP Request Headers and Response Headers
-7.1.3 Android HTTP Request Method: HttpURLConnection
-7.1.4 Android HTTP Request Method: HttpClient
-7.2.1 Android XML Data Parsing
-7.2.2 Android JSON Data Parsing
-7.3.2 Android File Download (1)
-7.3.3 Android File Download (2)
-7.4 Android Calling WebService
-7.5.1 Basic Usage of WebView (Web View)
-7.5.2 Basic Interaction Between WebView and JavaScript
-7.5.3 Considerations for WebView in Android 4.4 and Later
-7.5.6 WebView Handling Error Codes from Web Pages
-7.6.1 Network Basics Preparation for Socket Learning
-7.6.2 Socket Communication Based on TCP Protocol (1)
-7.6.3 Socket Communication Based on TCP Protocol (2)
-7.6.4 Socket Communication Based on UDP Protocol
-8.1.1 Summary of 13 Drawable Types in Android Part 1
-8.1.2 Summary of 13 Drawable Types in Android Part 2
-8.1.3 Summary of 13 Drawable Types in Android Part 3
-8.2.1 Comprehensive Analysis of Bitmap (Bitmap) Part 1
-8.2.2 OOM Issues Caused by Bitmap
-8.3.1 Detailed Explanation of Three Drawing Tool Classes
-8.3.2 Practical Examples of Drawing Classes
-8.3.3 Paint API — MaskFilter (Mask)
-8.3.4 Paint API — Xfermode and PorterDuff Detailed Explanation (Part 1)
-8.3.5 Paint API — Xfermode and PorterDuff Detailed Explanation (Part 2)
-8.3.6 Paint API — Xfermode and PorterDuff Detailed Explanation (Part 3)
- 8.3.7 Paint API - Xfermode and PorterDuff Explained (Part 4)
- 8.3.8 Paint API - Xfermode and PorterDuff Explained (Part 5)
- 8.3.9 Paint API - ColorFilter (Color Filter) (1/3)
- 8.3.10 Paint API - ColorFilter (Color Filter) (2/3)
- 8.3.11 Paint API - ColorFilter (Color Filter) (3/3)
- 8.3.12 Paint API - PathEffect (Path Effect)
- 8.3.13 Paint API - Shader (Image Rendering)
- 8.3.14 Paint Enumerations/Constants and ShadowLayer Shadow Effect
- 8.3.15 Paint API - Typeface (Font Style)
- 8.3.16 Canvas API Detailed (Part 1)
- 8.3.17 Canvas API Detailed (Part 2) Clipping Methods
- 8.3.18 Canvas API Detailed (Part 3) Matrix and drawBitmapMesh
- 8.4.1 Android Animation Collection - Frame Animation
- 8.4.2 Android Animation Collection - Tween Animation
- 8.4.3 Android Animation Collection - Property Animation - First Look
- 8.4.4 Android Animation Collection - Property Animation - Another Look
- 9.1 Using SoundPool to Play Sound Effects (Duang~)
- 9.2 MediaPlayer to Play Audio and Video
- 9.3 Using Camera to Take Photos
- 9.4 Using MediaRecord to Record Audio
- 10.1 TelephonyManager (Phone Manager)
- 10.2 SmsManager (SMS Manager)
- 10.3 AudioManager (Audio Manager)
- 10.4 Vibrator (Vibrator)
- 10.5 AlarmManager (Alarm Service)
- 10.6 PowerManager (Power Service)
- 10.7 WindowManager (Window Management Service)
- 10.8 LayoutInflater (Layout Service)
- 10.9 WallpaperManager (Wallpaper Manager)
- 10.10 Sensor Topic (1) - Introduction
- 10.11 Sensor Topic (2) - Orientation Sensor
- 10.12 Sensor Topic (3) - Accelerometer/Gyroscope Sensor
- 10.12 Sensor Topic (4) - Understanding Other Sensors
- 10.14 Android GPS Introduction
- 11.0《2015 Latest Android Basic Beginner Tutorial》Completion Celebration~
- 12.1 Android Practice: DrySister Look at Girls App (First Edition) - Project Setup and Simple Implementation
- 12.2 DrySister Look at Girls App (First Edition) - 2. Parsing Backend Data
- 12.3 DrySister Look at Girls App (First Edition) - 3. Image Loading Optimization (Writing an Image Cache Framework)
- 12.4 DrySister Look at Girls App (First Edition) - 4. Adding Data Caching (Introducing SQLite)
- 12.5 DrySister Look at Girls App (First Edition) - 5. Code Review, Adjustment, and Logging Class Writing
- 12.6 DrySister Look at Girls App (First Edition) - 6. Icon Creation, Obfuscation, Signing, APK Slimming, App Release