[英]Update ListView in Fragment after AlertDialog dismiss
我有一个包含ListView
的Fragment
。 我正在使用对话框将一些值添加到数据库,并且我想在关闭对话框后更新此ListView
。 另外,当我更改选项卡时,不会更新ListView
但是在打开和关闭应用程序时,也会更新ListView
。
Fragment
和Dialog
类如下:
分段:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_teams, container, false);
listViewTeams = rootView.findViewById(R.id.listView_teams);
TeamDatabase teamDatabase = new TeamDatabase(getContext());
teamDatabase.open();
arrayListTeam = teamDatabase.getAllTeams();
teamDatabase.close();
int resID = R.layout.team_list_item;
teamListArrayAdapter = new TeamListArrayAdapter(getContext(), resID, arrayListTeam);
listViewTeams.setAdapter(teamListArrayAdapter);
return rootView;
}
对话框onClick
方法:
@Override
public void onClick(View view) {
int id = view.getId();
switch (id){
case R.id.button_alertDialogAddTeam_cancel:
this.dismiss();
break;
case R.id.button_alertDialogAddTeam_ok:
Team team = new Team();
team.setName(editTextTeamName.getText().toString());
team.setCode(editTextTeamCode.getText().toString());
TeamDatabase teamDatabase = new TeamDatabase(getContext());
teamDatabase.open();
if(teamDatabase.addNewTeam(team)) {
Toast.makeText(getContext(), team.getCode() + " - " +
team.getName() + " was added successfully", Toast.LENGTH_SHORT).show();
}
this.dismiss();
break;
}
}
TeamDatabase类:
public static final String TABLE_NAME = "team";
private static final String KEY_ID = "id";
private static final String KEY_NAME = "name";
private static final String KEY_CODE = "code";
private static final String KEY_EMBLEM = "emblem";
private Context context;
public static final String CREATE_TABLE = "CREATE TABLE "+
TABLE_NAME + " ("+
KEY_ID + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, "+
KEY_NAME + " TEXT NOT NULL, "+
KEY_CODE + " TEXT NOT NULL, " +
KEY_EMBLEM + " TEXT);";
public TeamDatabase(Context context) {
super(context);
this.context = context;
}
public boolean addNewTeam(Team team){
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_NAME, team.getName());
contentValues.put(KEY_CODE, team.getCode());
return db.insert(TABLE_NAME, null, contentValues) > 0;
}
public ArrayList<Team> getAllTeams()
{
ArrayList<Team> teams = new ArrayList<Team>();
Cursor cursor = db.query(TABLE_NAME, new String[]{KEY_ID,
KEY_NAME,
KEY_CODE}, null, null, null, null, null);
while(cursor.moveToNext()) {
Team team = new Team();
team.setId(cursor.getInt(cursor.getColumnIndex(KEY_ID)));
team.setName(cursor.getString(cursor.getColumnIndex(KEY_NAME)));
team.setCode(cursor.getString(cursor.getColumnIndex(KEY_CODE)));
teams.add(team);
}
return teams;
}
DatabaseHelper类:
private static final String DATABASE_NAME = "fixtureCreator.db";
private static final int DATABASE_VERSION = 1;
public SQLiteDatabase db;
public DatabaseHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(TeamDatabase.CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersinon) {
Log.w("TaskDBAdapter", "Upgrading from version " +
oldVersion + " to " + newVersinon + ", which will destroy all old data");
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + TeamDatabase.TABLE_NAME);
onCreate(sqLiteDatabase);
}
public DatabaseHelper open() throws SQLException {
try{
db = this.getWritableDatabase();
}catch (SQLException e){
db = this.getReadableDatabase();
}
return this;
}
public void close(){
db.close();
}
在第一个活动中单击该项目时,请使用startActivityForResult()
启动第二个活动
然后在“第二个活动”中,关闭对话框后,在该按钮调用的onClick
中,
intent.putExtra("new data", "item text");
setResult(RESULT_OK, intent);
finish();
现在您回到第一个Activity,在这里您必须实现onActivityResult()
回调。
您可以从该意图的附加对象中提取数据,并在数组中设置相应项,然后调用notifyDataSetChanged()。
理想情况下,这就是您应该如何做。
您应该在关闭对话框之前调用notifyDataSetChanged
teamListArrayAdapter.notifyDataSetChanged();
您应该在下面更改类似这样的代码
@Override
public void onClick(View view) {
int id = view.getId();
switch (id){
case R.id.button_alertDialogAddTeam_cancel:
this.dismiss();
break;
case R.id.button_alertDialogAddTeam_ok:
Team team = new Team();
team.setName(editTextTeamName.getText().toString());
team.setCode(editTextTeamCode.getText().toString());
TeamDatabase teamDatabase = new TeamDatabase(getContext());
teamDatabase.open();
if(teamDatabase.addNewTeam(team)) {
Toast.makeText(getContext(), team.getCode() + " - " +
team.getName() + " was added successfully", Toast.LENGTH_SHORT).show();
}
arrayListTeam = teamDatabase.getAllTeams();
teamListArrayAdapter.notifyDataSetChanged();
this.dismiss();
break;
}
}
可以通过在每次单击Dialog
然后在适配器上调用notifyDataSetChanged()
后保存数据后获取数据来解决此问题。 但是,有一种更优雅的方式来实现这种行为,这将使用内容观察器解决您的两个问题。
如果数据库表中有内容观察者,则需要先声明一个引用表的URI。
public static final Uri DB_TABLE_TEAM_URI = Uri
.parse("sqlite://" + Constants.ApplicationPackage + "/" + DB_TABLE_TEAM);
// DB_TABLE_TEAM refers to the database table that you have for storing teams.
现在,在您的addNewTeam
函数中,您需要执行以下操作。
public boolean addNewTeam(Team team) {
// .. Save the team in database
// Notify the observer about the change in the content
context.getContentResolver().notifyChange(DBConstants.DB_TABLE_TEAM_URI, null);
}
每当在团队表中添加或更新条目时,都需要调用notifyChange()
函数。
现在,在“ Activity
或“ Fragment
您需要在cursor
上注册观察者,并从团队表中获取团队数据。
cursor = teamDatabase.getAllTeamsInCursor();
this.registerContentObserver(cursor, DBConstants.DB_TABLE_TEAM_URI);
现在填充您ListView
使用cursor
将它传递给你的适配器ListView
。 在团队表中插入新数据后,该列表将自动更新。
更新资料
修改TeamDatabase
类中的addNewTeam
函数,如下所示。
public static final Uri DB_TABLE_TEAM_URI = Uri
.parse("sqlite://" + Constants.ApplicationPackage + "/" + DB_TABLE_TEAM);
public boolean addNewTeam(Team team){
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_NAME, team.getName());
contentValues.put(KEY_CODE, team.getCode());
boolean success = db.insert(TABLE_NAME, null, contentValues) > 0;
context.getContentResolver().notifyChange(DBConstants.DB_TABLE_TEAM_URI, null);
return success;
}
要使用LoaderCallbacks
实现功能,首先需要在Fragment
implement
LoaderCallbacks
的接口。 因此,您的Fragment
的声明将看起来像。
public class TeamsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
// .... Code
}
现在,您需要重写LoaderCallbacks
接口随附的功能。
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new SQLiteCursorLoader(getActivity()) {
@Override
public Cursor loadInBackground() {
// Initialize your database
TeamDatabase teamDatabase = new TeamDatabase(getActivity());
Cursor cursor = teamDatabase.getAllTeams();
if (cursor != null) {
// Register the content observer here
this.registerContentObserver(cursor, DBConstants.DB_TABLE_TEAM_URI);
}
return cursor;
}
};
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Set the cursor in your adapter. Handle null values in your setCursor function in your adapter. The cursor might return null when the table is empty.
teamAdapter.setCursor(cursor);
teamAdapter.notifyDataSetChanged();
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
现在,在Fragment
onCreateView
函数中,您需要启动加载程序以从表中获取数据。
getLoaderManager().initLoader(0, null, this).forceLoad();
销毁加载程序,并在onDestroyView
函数中取消注册接收程序。
@Override
public void onDestroyView() {
getLoaderManager().destroyLoader(0);
super.onDestroyView();
}
我缺少要在此处添加的SQLiteCursorLoader
类。
package com.wooz.observer.databases;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
public abstract class SQLiteCursorLoader extends AsyncTaskLoader<Cursor> {
private final ForceLoadContentObserver mObserver;
private Uri mUri;
private String[] mProjection;
private String mSelection;
private String[] mSelectionArgs;
private String mSortOrder;
private Cursor mCursor;
/* Runs on a worker thread */
@Override
public abstract Cursor loadInBackground();
/**
* Registers an observer to get notifications from the content provider
* when the cursor needs to be refreshed.
*/
public void registerContentObserver(Cursor cursor, Uri observerUri) {
cursor.registerContentObserver(mObserver);
cursor.setNotificationUri(getContext().getContentResolver(), observerUri);
}
/* Runs on the UI thread */
@Override
public void deliverResult(Cursor cursor) {
try {
if (isReset()) {
// An async query came in while the loader is stopped
if (cursor != null) {
cursor.close();
}
return;
}
Cursor oldCursor = mCursor;
mCursor = cursor;
if (isStarted()) {
super.deliverResult(cursor);
}
if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
oldCursor.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Creates an empty unspecified CursorLoader. You must follow this with
* calls to {@link #setUri(Uri)}, {@link #setSelection(String)}, etc
* to specify the query to perform.
*/
public SQLiteCursorLoader(Context context) {
super(context);
mObserver = new ForceLoadContentObserver();
}
/**
* Creates a fully-specified CursorLoader. See
* {@link ContentResolver#query(Uri, String[], String, String[], String)
* ContentResolver.query()} for documentation on the meaning of the
* parameters. These will be passed as-is to that call.
*/
public SQLiteCursorLoader(Context context, Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
super(context);
mObserver = new ForceLoadContentObserver();
mUri = uri;
mProjection = projection;
mSelection = selection;
mSelectionArgs = selectionArgs;
mSortOrder = sortOrder;
}
/**
* Starts an asynchronous load of the contacts list data. When the result is ready the callbacks
* will be called on the UI thread. If a previous load has been completed and is still valid
* the result may be passed to the callbacks immediately.
* <p>
* Must be called from the UI thread
*/
@Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
/**
* Must be called from the UI thread
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
@Override
public void onCanceled(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
mCursor = null;
}
public Uri getUri() {
return mUri;
}
public void setUri(Uri uri) {
mUri = uri;
}
public String[] getProjection() {
return mProjection;
}
public void setProjection(String[] projection) {
mProjection = projection;
}
public String getSelection() {
return mSelection;
}
public void setSelection(String selection) {
mSelection = selection;
}
public String[] getSelectionArgs() {
return mSelectionArgs;
}
public void setSelectionArgs(String[] selectionArgs) {
mSelectionArgs = selectionArgs;
}
public String getSortOrder() {
return mSortOrder;
}
public void setSortOrder(String sortOrder) {
mSortOrder = sortOrder;
}
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
super.dump(prefix, fd, writer, args);
writer.print(prefix);
writer.print("mUri=");
writer.println(mUri);
writer.print(prefix);
writer.print("mProjection=");
writer.println(Arrays.toString(mProjection));
writer.print(prefix);
writer.print("mSelection=");
writer.println(mSelection);
writer.print(prefix);
writer.print("mSelectionArgs=");
writer.println(Arrays.toString(mSelectionArgs));
writer.print(prefix);
writer.print("mSortOrder=");
writer.println(mSortOrder);
writer.print(prefix);
writer.print("mCursor=");
writer.println(mCursor);
//writer.print(prefix); writer.print("mContentChanged="); writer.println(mContentChanged);
}
private class CursorLoaderContentObserver extends ContentObserver {
public CursorLoaderContentObserver() {
super(new Handler());
}
@Override
public boolean deliverSelfNotifications() {
return true;
}
@Override
public void onChange(boolean selfChange) {
onContentChanged();
}
}
}
在onCreateView中添加以下代码:
teamListArrayAdapter.notifyDataSetChanged();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.