我有一个Listview
,可以从sqlite数据库中提取和显示数据。数据库第一列中的数据显示在ListView
中,单击时,Activity
开始显示与第一列关联的列的其余部分。编辑数据时,需要更新ListView
以反映此情况,但除非重新启动应用程序,否则它不会显示更新。
我尝试在notifyDataSetChanged()
方法中调用startActivityForResult()
和onResume()
,但这不起作用。我应该使用什么方法来完成更新当前代码中的ListView
?
我理解可能会使用SimpleCursorAdapter
,并且我试图实现该代码但没有成功。我是一个新手,需要实际的代码才能理解需要做什么。
public class LoginList extends Activity implements OnClickListener, OnItemClickListener {
private ListView loginList;
private Button webLogin;
private ListAdapter loginListAdapter;
private ArrayList<LoginDetails> loginArrayList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_listview);
loginList = (ListView)
findViewById(R.id.loginlist);
loginList.setOnItemClickListener(this);
webLogin = (Button)
findViewById(R.id.button3);
webLogin.setOnClickListener(this);
loginArrayList = new ArrayList<LoginDetails>();
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
loginList.setAdapter(loginListAdapter);
}
@Override
public void onClick (View v) {
Intent webLoginIntent = new Intent (this, LoginPlusActivity.class);
startActivity(webLoginIntent);
}
public List<String> populateList () {
List<String> webNameList = new ArrayList<String>();
dataStore openHelperClass = new dataStore (this);
SQLiteDatabase sqliteDatabase = openHelperClass.getReadableDatabase();
Cursor cursor = sqliteDatabase.query(dataStore.TABLE_NAME_INFOTABLE, null, null, null, null, null, dataStore.COLUMN_NAME_SITE, null);
startManagingCursor(cursor);
while (cursor.moveToNext()) {
String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));
LoginDetails lpDetails = new LoginDetails();
lpDetails.setsName(sName);
lpDetails.setwUrl(wUrl);
lpDetails.setuName(uName);
lpDetails.setpWord(pWord);
lpDetails.setlNotes(lNotes);
loginArrayList.add(lpDetails);
webNameList.add(sName);
}
sqliteDatabase.close();
return webNameList;
}
@Override
protected void onResume() {
super.onResume();
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
loginList.setAdapter(loginListAdapter);
}
@Override
public void onItemClick(AdapterView<?> arg0 , View arg1, int arg2, long arg3) {
Toast.makeText(getApplicationContext(), "Selected ID :" + arg2, Toast.LENGTH_SHORT).show();
Intent updateDeleteLoginInfo = new Intent (this, UpdateDeleteLoginList.class);
LoginDetails clickedObject = loginArrayList.get(arg2);
Bundle loginBundle = new Bundle();
loginBundle.putString("clickedWebSite",clickedObject.getsName());
loginBundle.putString("clickedWebAddress",clickedObject.getwUrl());
loginBundle.putString("clickedUserName",clickedObject.getuName());
loginBundle.putString("clickedPassWord",clickedObject.getpWord());
loginBundle.putString("clickedNotes",clickedObject.getlNotes());
updateDeleteLoginInfo.putExtras(loginBundle);
startActivityForResult(updateDeleteLoginInfo, 0);
}
}
答案 0 :(得分:5)
这正是Loader
非常适合的。我建议你创建一个SimpleCursorAdapter
来将数据库绑定到UI(在这种情况下是ListView
),一个ContentProvider
与数据库接口,一个CursorLoader
来监控数据库进行更改,并在必要时更新UI。 Loader
将处理所有数据库更改,只需更新适配器即可更新ListView
。它看起来像预先做了很多工作,但是一旦配置就非常强大,并且可以在整个Android生命周期中工作。
这些教程应该会有所帮助:
答案 1 :(得分:5)
修改强>
private ArrayList<LoginDetails> loginArrayList = new ArrayList<LoginDetails>();;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_listview);
loginList = (ListView)
findViewById(R.id.loginlist);
loginList.setOnItemClickListener(this);
webLogin = (Button)
findViewById(R.id.button3);
webLogin.setOnClickListener(this);
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,loginArrayList );
loginList.setAdapter(loginListAdapter);
populateList();
}
@Override
public void onClick (View v) {
Intent webLoginIntent = new Intent (this, LoginPlusActivity.class);
startActivity(webLoginIntent);
}
public void populateList () {
loginListAdapter.clear();
loginArrayList.clear();
dataStore openHelperClass = new dataStore (this);
SQLiteDatabase sqliteDatabase = openHelperClass.getReadableDatabase();
Cursor cursor = sqliteDatabase.query(dataStore.TABLE_NAME_INFOTABLE, null, null, null, null, null, dataStore.COLUMN_NAME_SITE, null);
startManagingCursor(cursor);
while (cursor.moveToNext()) {
String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));
LoginDetails lpDetails = new LoginDetails();
lpDetails.setsName(sName);
lpDetails.setwUrl(wUrl);
lpDetails.setuName(uName);
lpDetails.setpWord(pWord);
lpDetails.setlNotes(lNotes);
loginArrayList.add(lpDetails);
webNameList.add(sName);
}
loginListAdapter.notifyDatasetChanged();
sqliteDatabase.close();
}
您正在丢失对列表视图的引用,指出您的列表未更新的原因......
在代码中进行此修改。 1.声明(全局)时初始化ArrayList。
ArrayList loginArrayList = new ArrayList<LoginDetails>();
直接将分配列表设置为适配器(onCreate)
loginListAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,loginArrayList);
在populateList()
中致电onCreate()
。
populateList()
而不是将数据添加到新列表中添加到与您的适配器关联的现有列表,即loginArrayList
如果您的列表在向adapter.clear()
添加数据之前在loginArrayList.clear()
中是全新的致电populateList()
和loginArrayList
。
将数据添加到loginArrayList
来电adapter.notifyDataSetChanged()
这应该有用......
答案 2 :(得分:0)
我的推荐。
SimpleCursorAdapter
并制作您的应用
更快更短的代码。Cursor
和Adapter
使用。swapCursor(newCursor)
。这将在保持滚动位置的同时更新您的列表。答案 3 :(得分:0)
如果您手动创建适配器的后备数据(在这种情况下,您使用的是ArrayAdapter - 在很多情况下完全可以接受),那么当数据库发生更改时,您需要重新查询数据库,重新创建数据集,更改适配器的支持数据集,并告诉列表数据集已更改。
实现此目的的一种方法可能是广播一个意图,让您的活动知道执行上述步骤(通过使用BroadcastReceiver捕获该意图)。
答案 4 :(得分:0)
这是我用于编辑每一行的示例代码以及listview的数据库我希望它能帮到你
首先创建我创建一个适配器名称“ListAdapterItem.java”
import java.util.ArrayList;
import java.util.HashMap;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class ListAdapterItem extends BaseAdapter {
private ArrayList<HashMap<String, Object>> list;
private Context context;
private RelativeLayout ll;
// used to keep selected position in ListView
private int selectedPos = -1; // init value for not-selected
private TextView label,label_id;
String name,id;
public ListAdapterItem (Context context,ArrayList<HashMap<String, Object>> list) {
this.list = list;
this.context = context;
}
public void setSelectedPosition(int pos) {
selectedPos = pos;
// inform the view of this change
notifyDataSetChanged();
}
public int getSelectedPosition() {
return selectedPos;
}
public View getView(int position, View convertView, ViewGroup parent) {
ll = (RelativeLayout) LayoutInflater.from(this.context).inflate(R.layout.data_list_item, null);
// get text view
label = (TextView) ll.findViewById(R.id.txtview_country_name);
label_id=(TextView) ll.findViewById(R.id.txtview_id);
id=list.get(position).get("Id").toString();
name = list.get(position).get("Name").toString();
label.setText(name);
label_id.setText(id);
return ll;
}
public int getCount() {
return this.list.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
}
这是我的data_list_item
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="@+id/txtview_id"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_margin="8dp"
android:layout_marginRight="2dp"
android:textColor="@android:color/black"
android:textSize="22dp"
android:visibility="invisible"/>
<TextView
android:id="@+id/txtview_country_name"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_margin="8dp"
android:layout_marginRight="2dp"
android:textColor="@android:color/black"
android:textSize="22dp" />
</RelativeLayout>
主要类“Main.java”
public class Main extends Activity implements OnClickListener {
String name;
SQLiteDatabase db;
Cursor cursor;
private ProgressDialog progressDialog;
public ListAdapterItem list_adapter;
private ArrayList<HashMap<String, Object>> lst_data;
private HashMap<String, Object> hm;
private ListView listview;
private String list_id;
private int counter_id,selectedPosition;
private View selectedView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
lst_data = new ArrayList<HashMap<String, Object>>();
listview = (ListView) findViewById(R.id.list);
new FetchDB().execute();
}
private class FetchDB extends AsyncTask<String, Void,ArrayList<HashMap<String, Object>>> {
protected void onPreExecute() {
progressDialog = ProgressDialog.show(Main.this,"Fetching Data", "Loading,Please wait...", true);
}
protected ArrayList<HashMap<String, Object>> doInBackground(String... lstStrings)throws IllegalArgumentException {
try {
db = openOrCreateDatabase("MyDB", MODE_PRIVATE, null);
cursor = db.rawQuery("SELECT * FROM person WHERE Id <> ''",null);
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
hm = new HashMap<String, Object>();
hm.put("Id",cursor.getInt(cursor.getColumnIndex("Id")));
hm.put("Name", cursor.getString(cursor.getColumnIndex("Name")));
lst_data.add(hm);
} while (cursor.moveToNext());
}// end of cursor.moveToFirst()
cursor.close();
}
} catch (Exception e) {
e.getMessage();
}
db.close();// database close
return lst_data;
}// end of doInbackgournd
@Override
protected void onPostExecute(ArrayList<HashMap<String, Object>> result) {
progressDialog.dismiss();
list_adapter = new ListAdapterItem(Main.this,result);
listview.setAdapter(list_adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
list_adapter.setSelectedPosition(arg2);
selectedPosition = arg2;
selectedView = arg1;
list_id=((TextView) selectedView.findViewById(R.id.txtview_id)).getText().toString();
}
});
}
}// end of FetchDBTask
private class SaveTask extends AsyncTask<String, Void,ArrayList<HashMap<String, Object>>> {
@Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(Main.this,"Saving Data", "Loading,Please wait...", true);
}
protected ArrayList<HashMap<String, Object>> doInBackground(String... arg0)throws IllegalArgumentException {
counter_id++;
name = editext_name.getText().toString();
hm = new HashMap<String, Object>();
hm.put("Id",counter_id);
hm.put("Name",name);
lst_data.add(hm);
saveDB();
return lst_data;
}// end of doInbackgournd
protected void onPostExecute(ArrayList<HashMap<String, Object>> result) {
progressDialog.dismiss();
list_adapter = new ListAdapterItem(Main.this,result);
listview.setAdapter(list_adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
list_adapter.setSelectedPosition(arg2);
selectedPosition = arg2;
selectedView = arg1;
list_id=((TextView) selectedView.findViewById(R.id.txtview_id)).getText().toString();
}
});
}
}// end of saveTask
public void saveDB(){
String sql;
db = openOrCreateDatabase("MyDB", MODE_PRIVATE, null);
// create table if not e exist
db.execSQL("CREATE TABLE IF NOT EXISTS person(Name VARCHAR ,Id INT(3));");
sql = "SELECT * FROM person WHERE Id="+list_id; //selected or click row in list item
Cursor cursor = db.rawQuery(sql, null);
if (cursor.moveToFirst()) {
String sqlUpdate = "UPDATE person SET Name=? WHERE Id="+db_id;
db.execSQL(sqlUpdate, new Object[] {db_name});
cursor.close();
db.close();// database close
} else {// empty insert
String sqlInsert = "INSERT INTO person VALUES (?,"+null+")";
db.execSQL(sqlInsert, new Object[] {db_name,db_address,db_phone,db_email,db_license,db_comments,db_company,db_policy,db_phone_insurance,vehc_year,vehc_make,vehc_model,vehc_license,vehc_vinnum,vehc_color,db_position });
cursor.close();
db.close();// database close
}
}
//Edit by row
private class EditData extends AsyncTask<String, Void,ArrayList<HashMap<String, Object>>> {
protected void onPreExecute() {
progressDialog = ProgressDialog.show(Main.this,"Saving Data", "Loading Please wait...", true);
}
protected ArrayList<HashMap<String, Object>> doInBackground(String... id)throws IllegalArgumentException {
name = editext_name.getText().toString();
hm = new HashMap<String, Object>();
hm.put("Id",counter_id);
hm.put("Name",name);
lst_data.set(selectedPosition, hm); //specific row update
list_id=Integer.parseInt(edit_counter);
saveDB();
return lst_data;
}// end of doInbackgournd
protected void onPostExecute(ArrayList<HashMap<String, Object>> result) {
progressDialog.dismiss();
list_adapter = new ListAdapterItem(Main.this,result);
listview.setAdapter(list_adapter);
}
}
}
和main_layout.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="vertical" >
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@android:color/transparent"
android:cacheColorHint="#00000000"
android:dividerHeight="2dp"
android:paddingTop="8dp"
android:transcriptMode="normal" />
</LinearLayout>
在listview中的每个listrow中指定您的ID,希望这能回答您的问题
答案 5 :(得分:0)
我认为在while块之前的populate()方法中你应该调用loginListAdapter.notifyDataSetChanged()和loginListAdapter.clear(); 这将清除适配器并通知它新的数据列表。
该块将如下所示:
loginListAdapter.notifyDataSetChanged();
loginListAdapter.clear();
while (cursor.moveToNext()) {
String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));
LoginDetails lpDetails = new LoginDetails();
lpDetails.setsName(sName);
lpDetails.setwUrl(wUrl);
lpDetails.setuName(uName);
lpDetails.setpWord(pWord);
lpDetails.setlNotes(lNotes);
loginArrayList.add(lpDetails);
webNameList.add(sName);
}
我刚编辑,因为您调用通知和清除的顺序不正确。清除必须在通知之后发生,这正是我从我的经验中获得的,除非适配器不会重绘列表。
答案 6 :(得分:0)
试试此代码
在公共区域添加变量:List<String> arrayList = new ArrayList<String>();
并在onCreate()中添加:
arrayList = populateList();
//然后在适配器中添加变量,如此
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, arrayList );
在onResume()中这段代码:
@Override
protected void onResume() {
super.onResume();
loginArrayList.clear();
arrayList.clear();
arrayList = populateList();
loginListAdapter.notifyDataSetChanged()
}
如果你解决了,请告诉我们。