【问题标题】:How do I change custom CursorAdapter to display only specific rows in the listview for a given fragment?如何更改自定义 CursorAdapter 以仅在列表视图中显示给定片段的特定行?
【发布时间】:2018-10-07 15:51:34
【问题描述】:

我的应用程序中的三个片段 Fragment1、Fragment2、Fragment3 使用单个自定义 CursorAdapter 类 TaskCursorAdapter 在列表视图中显示单个表的内容。这是课程:

public class TaskCursorAdapter extends CursorAdapter {
    public TaskCursorAdapter(Context context, Cursor c) {
        super(context, c, 0 /* flags */);
    }
    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return LayoutInflater.from(context).inflate(R.layout.list_item_task, parent, false);
    }
    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        TextView titleTextView = (TextView) view.findViewById(R.id.task_title);
        TextView detailsTextView = (TextView) view.findViewById(R.id.task_details);
        int titleColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_TITLE);
        int detailsColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_DETAILS);
        String taskTitle = cursor.getString(titleColumnIndex);
        String taskDetails = cursor.getString(detailsColumnIndex);
        if (TextUtils.isEmpty(taskDetails)) {
            taskDetails = context.getString(R.string.unknown_task);
        }
        titleTextView.setText(taskTitle);
        detailsTextView.setText(taskDetails);
    }
}

该表在 Contract 类中指定为 TaskEntry。它还有另一个名为 TaskEntry.COLUMN_TASK_STATUS="status" 的列。可能的值是 0、1 或 2。目前,所有项目都显示在两个片段中。但是,我想让它只在 Fragment1 中显示 status=0 的行,在 Fragment2 中显示 status=1 的行,在 Fragment3 中显示 status=2 的行。

我在 bindView 方法中尝试了以下方法:

int taskStatus = Integer.parseInt(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_STATUS)));
if(taskStatus==0) { //code in bindView }

这导致在所有片段中仅显示状态 = 0 的项目,但它留下了一个空的膨胀视图来代替状态不是 0 的项目。 此外,我找不到传递信息以使其特定于 Fragment1 的方法。

我应该如何根据状态值和片段有条件地显示行?

编辑: 什么有效:

我没有在 TaskCursorAdapter 中尝试这个,而是在 onCreateLoader 方法中使用条件查询,如下所示:

public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    String selectionArgs[] = {"<status>"};
    String[] projection = {
            TaskEntry._ID,
            TaskEntry.COLUMN_TASK_TITLE,
            TaskEntry.COLUMN_TASK_DETAILS};
    return new CursorLoader(this.getActivity(), TaskEntry.CONTENT_URI, projection,
            TaskEntry.COLUMN_TASK_STATUS + " = ?", selectionArgs, null);
}

【问题讨论】:

    标签: android android-fragments android-cursoradapter


    【解决方案1】:

    试试这个:

    public class TaskCursorAdapter extends CursorAdapter {
        private int statusCode;        
    
        public TaskCursorAdapter(Context context, Cursor c) {
            super(context, c, 0 /* flags */);
        }
    
        public setStatusCode(int statusCode){
            this.statusCode = statusCode;
        }
    
        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            int currentStatusCode = Integer.parseInt(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_STATUS)));
            if(statusCode == currentStatusCode){
                return LayoutInflater.from(context).inflate(R.layout.list_item_task, parent, false);
             } else return null;
        }
    
        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            if(view != null){
                TextView titleTextView = (TextView) view.findViewById(R.id.task_title);
                TextView detailsTextView = (TextView) view.findViewById(R.id.task_details);
                int titleColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_TITLE);
                int detailsColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_DETAILS);
                String taskTitle = cursor.getString(titleColumnIndex);
                String taskDetails = cursor.getString(detailsColumnIndex);
                if (TextUtils.isEmpty(taskDetails)) {
                    taskDetails = context.getString(R.string.unknown_task);
                }
                titleTextView.setText(taskTitle);
                detailsTextView.setText(taskDetails);
            }
        }
    }
    

    并在您的每个片段中执行此操作,分别传入您的状态代码:

     yourAdapter = new TaskCursorAdapter(this, yourDataCursor);
     yourAdapter.setStatusCode(YOUR_STATUS_CODE);
     yourListView.setAdapter(yourAdapter);
    

    EDIT(事实证明我们无法从 CursorAdapter#newView() 返回 null

    所以我猜你必须在实例化一个新的 TaskCursorAdapter 之前过滤每个 Fragment 中的光标,并传入过滤后的光标而不是原始光标。您可以为此使用 CursorWrapper 类。这个答案可能会给你一个想法:https://stackoverflow.com/a/7343721/8354184

    【讨论】:

    • 我试过这个,这导致应用程序一启动就终止,但出现以下异常:java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View .getImportantForAccessibility()' 在空对象引用上
    • 添加条件 (view!=null) 似乎无助于从 newView 方法返回 null 的情况。但是在 bindView 中测试 statusCode 会导致不必要的视图被夸大。
    • 我明白了。所以我认为你应该为每个片段使用不同的游标。为此,我建议不要每次都查询数据库,而是使用您的过滤结果逻辑实现一个 CursorWrapper - 根据它们的状态代码 - 并使用它而不是您的原始光标。
    • 好吧,我对使用不同的游标犹豫不决,想知道这是否是低效或不好的做法。谢谢,如果没有解决方法,我会接受您使用不同光标的建议。
    • 只要确保不要每次都查询数据库,因为那样会非常昂贵。相反,获取一次光标,然后使用 CursorWrapper 过滤行。您可能需要编写自己的自定义 CursorWrapper 以获得所需的功能:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    • 2015-06-20
    相关资源
    最近更新 更多