【问题标题】:addRow adds to top of listView correctly first time, then adds to bottom of the listaddRow 第一次正确添加到 listView 顶部,然后添加到列表底部
【发布时间】:2017-02-21 04:50:07
【问题描述】:

我从屏幕下半部分的列表视图中获取光标并将其添加到上半部分列表视图中。这不是像预期的那样工作 100%。我第一次单击底部行时,它会将该行正确添加到位置 0 的顶部列表视图中,并且在其下方有该行(应用程序打开时该行存在)。太好了,这就是我想要的,除非我从底部列表中单击另一行。该行添加在 2 的位置,基本上不会变为 0 并将其他 2 向下推。

现在,这对我想要的不正确,并且相信这总是会弄乱我的 onClick 事件,因为从被点击的 topList 传递的数据现在是错误的。不确定两者是否相关,因此尝试至少让 topList 正确显示,然后我可以进行更多调试,看看为什么传递的数据不正确。

这是我用来更新 topList 的代码,光标从 bottomList 传递

    public class TopFragment extends Fragment {
    public Cursor mTopCursor;
    EmployeeDBHandler dbHandler;
    ListView mTopListView;
    public static MatrixCursor customCursor1;
    int flag = 0;
    TopListCursorAdapter mTopAdapter;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_top_list, container, false);
        String table = "employees";
        customCursor1 = new MatrixCursor(new String[]{"_id", "Employee_number", "First_name",
                "Last_name", "Payroll_title", "ThumbnailData", "Email", "Phone_mobile", "Phone_office", "Cost_center_id",
                "Has_direct_reports", "Manager_employee_number"});
        dbHandler = EmployeeDBHandler.getInstance(getContext());
        SQLiteDatabase db = dbHandler.getWritableDatabase();
        int mStartingEmployeeID = mStartingNumber;
        mTopCursor = db.rawQuery("SELECT * FROM " + table + " WHERE " + "Employee_number" + "=" + mStartingEmployeeID, null);
        mTopListView = (ListView) view.findViewById(R.id.mTopList);
        mTopAdapter = new TopListCursorAdapter(getContext(), mTopCursor);
        mTopListView.setAdapter(mTopAdapter);
        customCursor1.close();
        db.close();
        return view;

    }

    public void update(Cursor cursor) {
        if (cursor.moveToFirst()) {
            customCursor1.addRow(new Object[]{cursor.getInt(0), cursor.getString(cursor.getColumnIndex("Employee_number")), cursor.getString(2),
                    cursor.getString(3), cursor.getString(6), cursor.getString(9), cursor.getString(8), cursor.getString(4),
                    cursor.getString(5), cursor.getString(10), cursor.getString(7), cursor.getString(11)});
            if (flag == 0) {
                customCursor1.addRow(new Object[]{mTopCursor.getInt(0), mTopCursor.getString(cursor.getColumnIndex("Employee_number")), mTopCursor.getString(2),
                        mTopCursor.getString(3), mTopCursor.getString(6), mTopCursor.getString(9),
                        mTopCursor.getString(8), mTopCursor.getString(4), mTopCursor.getString(5),
                        mTopCursor.getString(10), mTopCursor.getString(7), mTopCursor.getString(11)});
                flag++;
            } else {
                flag = 1;
            }
            mTopAdapter.changeCursor(customCursor1);
            customCursor1.close();
        }
    }
}

public class TopListCursorAdapter extends CursorAdapter {

    public interface TopListClickListener {
        void onTopListClick(Cursor cursor);
    }

    private TopListClickListener mCallback;

    public TopListCursorAdapter(Context context, Cursor cursor) {
        super(context, cursor, 0);
        if(!(context instanceof TopListClickListener)) {
            throw new ClassCastException("Content must implement BottomListClickListener");
        }
        this.mCallback = (TopListClickListener) context;
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return LayoutInflater.from(context).inflate(R.layout.contact_cardview_top, parent, false);
    }

    @Override
    public void bindView(View view, final Context context, final Cursor cursor) {
        ViewHolder holder;
        holder = new ViewHolder();
        holder.tvFirstName = (TextView) view.findViewById(R.id.personFirstName);
        holder.tvLastName = (TextView) view.findViewById(R.id.personLastName);
        holder.tvTitle = (TextView) view.findViewById(R.id.personTitle);
        holder.mPeepPic = (ImageView) view.findViewById(R.id.person_photo);
        holder.mDetailsButton = (ImageButton) view.findViewById(R.id.fullDetailButton);
        holder.mTopCardView = (CardView) view.findViewById(R.id.mTopHomeScreenCV);

        String mFirstName = cursor.getString(cursor.getColumnIndexOrThrow("First_name"));
        String mLastName = cursor.getString(cursor.getColumnIndexOrThrow("Last_name"));
        String mPayrollTitle = cursor.getString(cursor.getColumnIndexOrThrow("Payroll_title"));
        String mThumbnail = cursor.getString(cursor.getColumnIndexOrThrow("ThumbnailData"));

        holder.tvFirstName.setText(mFirstName);
        holder.tvLastName.setText(mLastName);
        holder.tvTitle.setText(mPayrollTitle);

        if (mThumbnail != null) {
            byte[] imageAsBytes = Base64.decode(mThumbnail.getBytes(), Base64.DEFAULT);
            Bitmap parsedImage = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
            holder.mPeepPic.setImageBitmap(parsedImage);
        } else {
            holder.mPeepPic.setImageResource(R.drawable.img_place_holder_adapter);
        }


        final int position = cursor.getPosition();
        holder.mDetailsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cursor.moveToPosition(position);
                String mEmployeeNumber = cursor.getString(cursor.getColumnIndex("Employee_number"));
                String mFirstName = cursor.getString(cursor.getColumnIndex("First_name"));
                String mLastName = cursor.getString(cursor.getColumnIndex("Last_name"));
                String mTitle = cursor.getString(cursor.getColumnIndex("Payroll_title"));
                String mPic = cursor.getString(cursor.getColumnIndex("ThumbnailData"));
                String mEmail = cursor.getString(cursor.getColumnIndex("Email"));
                String mPhoneMobile = cursor.getString(cursor.getColumnIndex("Phone_mobile"));
                String mPhoneOffice = cursor.getString(cursor.getColumnIndex("Phone_office"));
                String mCostCenter = cursor.getString(cursor.getColumnIndex("Cost_center_id"));
                String mHasDirectReports = cursor.getString(cursor.getColumnIndex("Has_direct_reports"));
                String mManagerNumber = cursor.getString(cursor.getColumnIndex("Manager_employee_number"));
                Intent mIntent = new Intent(context, EmployeeFullInfo.class);
                mIntent.putExtra("Employee_number", mEmployeeNumber);
                mIntent.putExtra("First_name", mFirstName);
                mIntent.putExtra("Last_name", mLastName);
                mIntent.putExtra("Payroll_title", mTitle);
                mIntent.putExtra("ThumbnailData", mPic);
                mIntent.putExtra("Email", mEmail);
                mIntent.putExtra("Phone_mobile", mPhoneMobile);
                mIntent.putExtra("Phone_office", mPhoneOffice);
                mIntent.putExtra("Cost_center_id", mCostCenter);
                mIntent.putExtra("Has_direct_reports", mHasDirectReports);
                mIntent.putExtra("Manager_employee_number", mManagerNumber);
                mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                v.getContext().startActivity(mIntent);
            }
        });

        holder.mTopCardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mCallback != null) {
                    mCallback.onTopListClick(cursor);
                    Log.i("FROMCLICK", DatabaseUtils.dumpCursorToString(cursor));
                }
            }
        });
    }

    public static class ViewHolder {
        TextView tvFirstName;
        TextView tvLastName;
        TextView tvTitle;
        ImageView mPeepPic;
        ImageButton mDetailsButton;
        CardView mTopCardView;
    }
}

@Override
    public void onTopListClick(Cursor cursor) {
        Log.i("FistClickBeforePassing", DatabaseUtils.dumpCursorToString(cursor));
        BottomFragment bottomFragment = (BottomFragment) getSupportFragmentManager().findFragmentById(R.id.bottomFragment);
        bottomFragment.refreshList(cursor);
    }

【问题讨论】:

  • 您不应该使用游标将数据传递给适配器,您可以将游标的结果存储在数组或列表中并将其传递给适配器。每当您想更新您的 listView 时,您只需要更新数组或列表,然后通过适配器的 notifyDataSetChange 方法通知适配器更改。
  • 不知道为什么当 Android 有一个接受光标的适配器时不能传递光标?但这对我从底部而不是顶部填充列表视图的问题有何帮助?
  • 对不起!我的错,我忘记了 CursorAdapter,我以为您使用的是 ListAdapter 的 BaseAdapter 之类的东西。但正如@A.A 所说,您不需要每次都创建新的适配器实例。

标签: android listview android-cursor


【解决方案1】:

您无需在每次更新光标时都创建新的适配器。使用 mTopAdapter 作为在 onCreateView() 中初始化的成员,然后使用以下方法更新 update() 方法中的光标:

mTopAdapter.changeCursor(customCursor1);
mtopAdapter.notifyDataSetChanged();

更新:始终将mTopCursor 中的行保留为最后一行

基于this answer,您可以使用MergeCursor 将您的customCursor1mTopCursor 合并为一个供适配器使用的新光标:

public void update(Cursor cursor) {
    if (cursor.moveToFirst()) {
        customCursor1.addRow(new Object[]{cursor.getInt(0), cursor.getString(cursor.getColumnIndex("Employee_number")), cursor.getString(2),
                cursor.getString(3), cursor.getString(6), cursor.getString(9), cursor.getString(8), cursor.getString(4),
                cursor.getString(5), cursor.getString(10), cursor.getString(7), cursor.getString(11)});


        MergeCursor newCursor = new MergeCursor(new Cursor[] {customCursor1, mTopCursor});
        mTopAdapter.swapCursor(newCursor);
        mtopAdapter.notifyDataSetChanged();
        customCursor1.close();
    }
}

【讨论】:

  • 我添加了您的建议(见上文)。第一次点击就像以前一样工作,现在第二次点击甚至没有将该行显示到 topList 中。
  • 尝试添加mTopAdapter.notifyDataSetChanged()
  • 现在第一次点击后的每次点击都有效,但方式相同。只是添加到列表的底部,而不是像第一次点击那样添加到顶部。
  • 我认为这是因为您的 if (flag == 0) 仅在第一次更新时被调用,但不会在以下任何更新时调用,导致新行在末尾正常添加
  • 当时的想法是一样的,关于如何使标志中的代码最后的任何建议?我需要那行已经在那里。但应该始终在列表的最后一行。也不想一遍又一遍地创建它,因为它是相同的数据。
【解决方案2】:

您是否在适配器上尝试过 notifyDataSetChanged?

在我的自定义适配器中,它看起来像这样:

public void removeAllItems(MyDbHelper dbHelper)
    {
        //Go ahead and delete everything 
        ...
        notifyDataSetChanged();
    }

还有其他类似的变化不大的选项,例如:

    notifyItemInserted(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, mInjections.size());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多