Android:RecyclerView 项目的 onClick() 在另一个 activity 调用 finish() 后无意中激活(由该 RecyclerView 启动)

Android: RecyclerView item's onClick() unintentionally activated after call to finish() by another activity (which was started by that RecyclerView)

我创建了一个带有 RecyclerView 的 "ListItemActivity",其中显示了与我的项目 class 实例关联的图像。

这些图像上有一个 onClick 方法,可以打开另一个 "ItemDetailActivity" 显示有关该特定项目的更多详细信息。

在 "ItemListActivity" 中有一个浮动操作按钮,它启动 "ItemAddActivity" 以添加新项目。当用户在此 activity 中并添加一个新项目时,他们单击一个调用 finish() 和 returns 的按钮到 "ListItemActivity".

一切正常,除了:

在 "ItemAddActivity" 中添加新项目并调用 finish() 后,我们返回到 "ItemListActivity",有时(通常情况下)似乎"ItemListActivity" 的 RecyclerView 中看似随机的图像被激活。

我不确定这是否与单击 "ItemAddActivity" 按钮本身有关,或者我不知道的 RecyclerView 的某些功能、finish() 的使用或 . .. ?

如果您需要更多信息或代码,请告诉我。

"ItemListActivity":

public class ItemListActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private ClosetSampleViewModel mViewModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_item_list);

    Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
    setSupportActionBar(myToolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    mRecyclerView = findViewById(R.id.item_list_rv);
    final ItemListAdapter adapter = new ItemListAdapter(this);
    mRecyclerView.setAdapter(adapter);
    mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, LinearLayoutManager.VERTICAL));

    mViewModel = ViewModelProviders.of(this).get(ClosetSampleViewModel.class);
    mViewModel.getAllItems().observe(this, new Observer<List<Item>>() {
        @Override
        public void onChanged(@Nullable List<Item> items) {
            adapter.setItems(items);
        }
    });
}

public void addItem(View view) {
    Intent intent = new Intent(this, ItemAddActivity.class);
    startActivity(intent);
}

public void viewItemDetail(View view) {
    final int itemPosition = mRecyclerView.getChildLayoutPosition(view);
    mViewModel.getAllItems().observe(this, new Observer<List<Item>>() {
        @Override
        public void onChanged(@Nullable List<Item> items) {
            Item item = items.get(itemPosition);
            Intent intent = new Intent(getApplicationContext(), ItemDetailActivity.class);
            intent.putExtra("itemId", item.getId());
            startActivity(intent);
        }
    });
}

}

"ItemListAdapter":

public class ItemListAdapter extends RecyclerView.Adapter<ItemListAdapter.ItemViewHolder> {
private final LayoutInflater mInflater;
private List<Item> mItems;

public ItemListAdapter(Context context) {
    mInflater = LayoutInflater.from(context);
}

@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = mInflater.inflate(R.layout.item_list_rv_item, parent, false);
    return new ItemViewHolder(itemView);

}

@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    if (mItems != null) {
        Item currentItem = mItems.get(position);

        String uriString = "none";
        if (currentItem.getImageUri() != null) {
            uriString = currentItem.getImageUri().toString();

            // TODO
            GlideApp.with(holder.pictureImageView.getContext()).load(uriString).placeholder(R.color.colorPrimaryDark).dontTransform().into(holder.pictureImageView);
        } else {
            holder.pictureImageView.setVisibility(View.INVISIBLE);
        }

    } else {
        // TODO: data not ready yet.
    }
}

public void setItems(List<Item> items) {
    mItems = items;
    notifyDataSetChanged();
}

@Override
public int getItemCount() {
    return mItems == null ? 0 : mItems.size();
}


class ItemViewHolder extends RecyclerView.ViewHolder {
    private final ImageView pictureImageView;

    private ItemViewHolder(View itemView) {
        super(itemView);
        pictureImageView = itemView.findViewById(R.id.item_list_rv_image);
    }
}

}

RecyclerView 项目的布局:

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_list_rv_image"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimaryDark"
    android:adjustViewBounds="true"
    android:padding="5dp"
    android:layout_margin="3dp"
    android:onClick="viewItemDetail" />

"ItemListActivity" 的布局:

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ItemListActivity">

<!-- Load the toolbar here -->

<android.support.v7.widget.RecyclerView
    android:id="@+id/item_list_rv"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:listitem="@layout/item_list_rv_item"/>

<android.support.design.widget.FloatingActionButton
    android:id="@+id/item_list_fab"
    app:fabSize="normal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="end|bottom"
    android:layout_margin="16dp"
    android:layout_marginEnd="16dp"
    android:layout_marginBottom="16dp"
    android:src="@drawable/ic_add_white_24dp"
    android:background="@color/colorAccent"
    android:onClick="addItem" />

</android.support.design.widget.CoordinatorLayout>

相关代码来自"ItemAddActivity":

public void onAddItemClicked(View view) {

    if (currentPhotoPath == null) {
    Toast.makeText(this, "Can't add item without image.", Toast.LENGTH_LONG).show();
    } else {
        final String itemName = itemNameEditText.getText().toString();
        final String itemDescription = itemDescriptionEditText.getText().toString();

        // Image set for this Item.
        final Uri imageUri = Uri.parse(currentPhotoPath);

        // Set the photo path to null in the shared prefs so we don't accidently delete it next time.
        SharedPreferences prefs = getApplicationContext().getSharedPreferences(ITEM_IMAGE_SHARED_PREFS_FILE, MODE_PRIVATE);
        SharedPreferences.Editor prefsEditor = prefs.edit();
        prefsEditor.putString(PREF_PHOTO_PATH, null);
        prefsEditor.apply();


        if (itemCategorySpinner.getSelectedItemPosition() >= 0) {
            mViewModel.getAllCategories().observe(this, new Observer<List<Category>>() {
            @Override
            public void onChanged(@Nullable List<Category> categories) {
                addItem(new Item(itemName, itemDescription, imageUri, categories.get(itemCategorySpinner.getSelectedItemPosition())));
            }
            });

        } else {
            addItem(new Item(itemName, itemDescription, imageUri, null));
            }


    }

}

private void addItem(Item item) {
mViewModel.insertItem(item);
finish();

}

"ItemAddActivity" 的布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ItemAddActivity">

<!-- Load the toolbar here -->

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

<EditText
    android:id="@+id/item_name"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="text"
    android:importantForAutofill="no"
    android:hint="@string/item_name" />

<EditText
    android:id="@+id/item_description"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="text"
    android:importantForAutofill="no"
    android:hint="@string/item_description" />

<android.support.v7.widget.AppCompatSpinner
    android:id="@+id/item_category_spinner"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

<Button
    android:id="@+id/take_photo_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/take_photo"
    android:onClick="onTakePhotoClicked" />

<Button
    android:id="@+id/add_item_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/add_item"
    android:onClick="onAddItemClicked"/>

<ImageView
    android:id="@+id/item_photo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="gone"/>

</LinearLayout>

</android.support.design.widget.CoordinatorLayout>

截图: ItemListActivity ItemAddActivity

我一直在为这个绞尽脑汁,我想不通这是怎么回事。如果缺少什么,请告诉我。我在使格式正常工作时遇到了很多麻烦。

非常非常感谢。

viewItemDetail 方法看起来很奇怪。第一次单击后,您已经注册了一个观察者,因此只要有新项目可用,它就会启动 ItemDetailActivity。为什么要注册一个观察者来启动activity。您获得了获取项目的索引。从回收者视图中获取适配器,然后使用索引获取项目,然后使用 itemid 触发一个 intent。