gpt4 book ai didi

java - 当使用 CursorAdapter 的回调时,调用 initLoader() 只工作一次

转载 作者:太空狗 更新时间:2023-10-29 16:36:23 26 4
gpt4 key购买 nike

在我的 Activity 中,我有一个代表医生的 ListView 。每行都有医生的名字和一个复选框。 I have implemented a callback interface so that when a doctor is selected, all other doctors are removed from the listview and only the selected doctor remains.

它似乎有效,因为一旦我选择了一位医生,所有其他人都被删除了。当我取消选中医生时,每个人都会被添加回来。但是,如果我现在选择一个不同的医生,原来的医生会留下来,其他的都被移除。

为了更好地解释这个问题,假设当我开始 Activity 时, ListView 中有两位医生,Joel 和 Sam。我想我想选择 Joel,所以我选择了,然后 Sam 从列表中删除了。然后,我意识到我错了,所以我取消选择 Joel,现在我在列表中看到了 Joel 和 Sam。最后,我选择山姆。但是,Sam 已从列表中删除,只剩下 Joel。

下面是适配器类的一些代码 fragment :

@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder viewHolder = (ViewHolder) view.getTag();

final long id = cursor.getLong(cursor.getColumnIndex(DoctorEntry._ID));
String firstName = cursor.getString(cursor.getColumnIndex(DoctorEntry.COLUMN_FIRSTNAME));

viewHolder.nameView.setText(firstName);

viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(mCallbacks != null){
if(isChecked){
mCallbacks.onDoctorChecked(id);
} else{
mCallbacks.onDoctorUnchecked();
}
}
}
});
}

public void onRegisterCallbacks(DoctorAdapterCallbacks activity){
mCallbacks = activity;
}

public static interface DoctorAdapterCallbacks{
void onDoctorChecked(long id);

void onDoctorUnchecked();
}

在我的 Activity 中,我有以下实现:

@Override
public void onDoctorChecked(long id) {
Bundle args = new Bundle();
args.putLong(SELECTED_DOCTOR_ID, id);
getSupportLoaderManager().initLoader(SELECTED_DOCTOR_LOADER, args, this);
}

@Override
public void onDoctorUnchecked() {
getSupportLoaderManager().initLoader(DOCTOR_LOADER, null, this);
}

DOCTOR_LOADER 是代表表中所有医生的 CursorLoader。 SELECTED_DOCTOR_ID 是仅供一位医生使用的 CursorLoader。

如果非要我猜的话,我的问题出在 bindView 方法上,因为我将 id 变量声明为 final。我这样做的原因是否则我会收到一个编译器错误:

error: local variable id is accessed from within inner class; needs to be declared final

声明变量 final 会引起麻烦吗?有人看到问题了吗?

编辑

我已将日志语句添加到适配器中的 onCheckedChangedListener 和 Activity 的 onDoctorSelected 中。使用上面的相同示例,我看到以下输出:

> onCheckedChanged : Selecting doctor id: 1 // Joel
> onDoctorSelected : Selecting doctor id: 1 // Joel
> onCheckedChanged : Selecting doctor id: 2 // Sam
> onDoctorSelected : Selecting doctor id: 2 // Sam

因此,它似乎确实看到我选择了 ID 为 2 的 Sam,并将 ID 2 传递给 initLoader() 方法,但 ListView 中只显示了 Joel(医生 ID 1),因为我首先选择了他。

编辑 2

根据请求,这里是 CursorLoader 方法的 fragment :

@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
switch(i){
case DOCTOR_LOADER:
return new CursorLoader(
this,
DoctorEntry.CONTENT_URI,
DOCTOR_COLUMNS,
null,
null,
null
);
case SELECTED_DOCTOR_LOADER:
long _id = bundle.getLong(SELECTED_DOCTOR_ID);
return new CursorLoader(
this,
DoctorEntry.buildDoctorUri(_id),
DOCTOR_COLUMNS,
DoctorEntry._ID + " = '" + _id + "'",
null,
null
);
default:
throw new UnsupportedOperationException("Unknown loader id: " + i);
}
}

@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
switch(cursorLoader.getId()){
case DOCTOR_LOADER:
case SELECTED_DOCTOR_LOADER:
mDoctorAdapter.swapCursor(cursor);
break;
default:
throw new UnsupportedOperationException("Unknown loader id: " + cursorLoader.getId());
}
}

编辑 3

我在 onCreateLoader 中添加了另一个日志语句,以查看正在使用哪个 ID 创建加载程序。然后,我看到了这个输出:

> onCheckedChanged : Selecting doctor id: 2
> onDoctorSelected : Selecting doctor id: 2
> onCreateLoader : Using id: 2
> // Unchecked, and now check doctor one
> onCheckedChanged : Selecting doctor id: 1
> onDoctorSelected : Selecting doctor id: 1

这不是打字错误。第二次选择医生时,似乎没有调用 onCreateLoader。我试过在 onDoctorChecked 中调用 destroyLoader() 但这似乎没有什么不同。

最佳答案

根据 initLoader() documentation :

Ensures a loader is initialized and active. If the loader doesn't already exist, one is created and (if the activity/fragment is currently started) starts the loader. Otherwise the last created loader is re-used.

In either case, the given callback is associated with the loader, and will be called as the loader state changes. If at the point of call the caller is in its started state, and the requested loader already exists and has generated its data, then callback onLoadFinished(Loader, D) will be called immediately (inside of this function), so you must be prepared for this to happen.

initLoader() 只初始化某个加载器 ID 一次,从那时起重复使用数据。如果您想放弃并重新创建一个新的加载器(即,使用一个新的 CursorLoader),请使用 restartLoader()取而代之(注意:restartLoader() 将在第一次时像 initLoader() 一样初始化加载程序,因此第一次运行时不需要任何特殊逻辑) .

关于java - 当使用 CursorAdapter 的回调时,调用 initLoader() 只工作一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27894572/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com