【问题标题】:How to set RecyclerView OnClickListener in Fragments?如何在 Fragments 中设置 RecyclerView OnClickListener?
【发布时间】:2019-05-22 15:02:56
【问题描述】:

我正在尝试创建一个新的Fragment,以显示在RecyclerView 中单击的项目的详细信息。我已经在活动中尝试过它并且效果很好,但我正在尝试将其转换为在片段上使用。每次我得到一个'空对象引用'

适配器

package com.umbrella.fragmenttest;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class BorrowedAdapter extends RecyclerView.Adapter<BorrowedAdapter.BorrowedViewHolder> {

    private Context mCtx;
    private List<Borrowed> borrowedList;

    public BorrowedAdapter(Context mCtx, List<Borrowed> borrowedList) {
        this.mCtx = mCtx;
        this.borrowedList = borrowedList;
    }

    @Override
    public BorrowedViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mCtx).inflate(R.layout.list_borrowed, parent, false);
        return new BorrowedViewHolder(view);
    }

    @Override
    public void onBindViewHolder(BorrowedViewHolder holder, int position) {
        Borrowed b = borrowedList.get(position);

        holder.textViewOwner.setText(b.getOwner());
        holder.textViewDesc.setText(b.getDesc());
        holder.textViewAmount.setText(String.valueOf(b.getAmount()));
    }

    @Override
    public int getItemCount() {
        return borrowedList.size();
    }

    class BorrowedViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        TextView textViewOwner, textViewDesc, textViewAmount;

        public BorrowedViewHolder(View itemView) {
            super(itemView);

            textViewOwner = itemView.findViewById(R.id.b_owner);
            textViewDesc = itemView.findViewById(R.id.b_description);
            textViewAmount = itemView.findViewById(R.id.b_amount);

            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            Borrowed borrowed = borrowedList.get(getAdapterPosition());

            AppCompatActivity activity = (AppCompatActivity) view.getContext();
            NavController navController = Navigation.findNavController(activity, R.id.hostfrag);
            navController.navigate(R.id.action_displayBorrowed2_to_updateBorrowedClass);
        }
    }
}

带有细节的片段类

package com.umbrella.fragmenttest;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;


public class UpdateBorrowedClass extends Fragment {
    private EditText editTextOwner, editTextDesc, editTextAmount;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.new_borrowed, container, false);

        editTextOwner = view.findViewById(R.id.u_owner);
        editTextDesc = view.findViewById(R.id.u_description);
        editTextAmount = view.findViewById(R.id.u_amount);

        Bundle bundle = getArguments();
        final Borrowed borrowed = (Borrowed) bundle.getSerializable("borrowed");

        loadBorrowed(borrowed);

        view.findViewById(R.id.button_update).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                updateBorrowed(borrowed);
            }
        });

        view.findViewById(R.id.button_delete).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
                builder.setTitle("Are you sure?");
                builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        deleteBorrowed(borrowed);
                    }
                });
                builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                    }
                });

                AlertDialog ad = builder.create();
                ad.show();
            }
        });

       return view;
    }

    private void loadBorrowed(Borrowed borrowed) {
        editTextOwner.setText(borrowed.getOwner());
        editTextDesc.setText(borrowed.getDesc());
        editTextAmount.setText(String.valueOf(borrowed.getAmount()));
    }

    private void updateBorrowed(final Borrowed borrowed) {
        final String sOwner = editTextOwner.getText().toString().trim();
        final String sDesc = editTextDesc.getText().toString().trim();
        final Double dAmount = Double.parseDouble(editTextAmount.getText().toString().trim());

        if (sOwner.isEmpty()) {
            editTextOwner.setError("Owner required");
            editTextOwner.requestFocus();
            return;
        }

        if (sDesc.isEmpty()) {
            editTextDesc.setError("Description required");
            editTextDesc.requestFocus();
            return;
        }

        if (dAmount.toString().isEmpty()) {
            editTextAmount.setError("Amount required");
            editTextAmount.requestFocus();
            return;
        }

        class UpdateBorrowed extends AsyncTask<Void, Void, Void> {

            @Override
            protected Void doInBackground(Void... voids) {
                //Creating an item
                borrowed.setOwner(sOwner);
                borrowed.setDesc(sDesc);
                borrowed.setAmount(dAmount);

                //Adding to database
                DatabaseClient.getInstance(getContext())
                        .borrowedDao()
                        .update(borrowed);
                return null;
            }

            //Returns to the {RecyclerViewFragment} because the item is created
            @Override
            protected void onPostExecute(Void aVoid) {
                super.onPostExecute(aVoid);

                DisplayBorrowed displayBorrowed = new DisplayBorrowed();
                getChildFragmentManager().beginTransaction().replace(R.id.mainer, displayBorrowed).addToBackStack(null).commit();
                Toast.makeText(getContext(), "Updated", Toast.LENGTH_LONG).show();
            }
        }
        UpdateBorrowed ut = new UpdateBorrowed();
        ut.execute();
    }


    private void deleteBorrowed(final Borrowed borrowed) {
        class DeleteBorrowed extends AsyncTask<Void, Void, Void> {

            @Override
            protected Void doInBackground(Void... voids) {
                DatabaseClient.getInstance(getContext())
                        .borrowedDao()
                        .delete(borrowed);
                return null;
            }

            //Returns to the {RecyclerViewFragment} because the item is created
            @Override
            protected void onPostExecute(Void aVoid) {
                super.onPostExecute(aVoid);

                DisplayBorrowed displayBorrowed = new DisplayBorrowed();
                getChildFragmentManager().beginTransaction().replace(R.id.mainer, displayBorrowed).addToBackStack(null).commit();
                Toast.makeText(getContext(), "Deleted", Toast.LENGTH_LONG).show();
            }
        }
        DeleteBorrowed dt = new DeleteBorrowed();
        dt.execute();
    }

}

运行日志

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.umbrella.fragmenttest, PID: 31428
    java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.Serializable android.os.Bundle.getSerializable(java.lang.String)' on a null object reference
        at com.umbrella.fragmenttest.UpdateBorrowedClass.onCreateView(UpdateBorrowedClass.java:31)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2439)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
        at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2646)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2416)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2372)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
        at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Application terminated.

【问题讨论】:

  • 您收到此错误是因为没有参数。创建片段时是否指定参数?
  • 当我使用活动时,我使用了intent.putExtra("borrowed", borrowed);,但使用片段我尝试了putSerializable 方法。这也给了我错误。
  • 看看我的答案并尝试一下
  • 分享你用来创建/启动这个片段的代码(新的UpdateBorrowedClass)
  • 启动片段的代码在适配器下面。我从 ClickListener 中启动它,因为只有这样才能打开 Fragment。

标签: java android android-recyclerview android-room


【解决方案1】:

看看这个链接:https://developer.android.com/guide/navigation/navigation-pass-data#bundle

在你的 onClick() 中

@Override
    public void onClick(View view) {
        Borrowed borrowed = borrowedList.get(getAdapterPosition());

        AppCompatActivity activity = (AppCompatActivity) view.getContext();
        NavController navController = Navigation.findNavController(activity, R.id.hostfrag);
        navController.navigate(R.id.action_displayBorrowed2_to_updateBorrowedClass);
    }

您应该使用借用的对象添加一个捆绑包作为参数,如下所示:

@Override
    public void onClick(View view) {
        Borrowed borrowed = borrowedList.get(getAdapterPosition());

        Bundle bundle = new Bundle();
        bundle.putSerializable("borrowed", borrowed);

        AppCompatActivity activity = (AppCompatActivity) view.getContext();
        NavController navController = Navigation.findNavController(activity, R.id.hostfrag);
        navController.navigate(R.id.action_displayBorrowed2_to_updateBorrowedClass, bundle);
    }

【讨论】:

  • 是的,这就是我尝试过的方法,但它为我的setText 方法提供了null object reference。我猜问题出在我 Fragment 中的 Bundle bundle = getArguments(); final Borrowed borrowed = (Borrowed) bundle.getSerializable("borrowed"); 某处。
  • 尝试在 OnBindViewHolder() 中设置你的 onclickListener
  • 不幸的是同样的效果:/
  • 捆绑包中是否包含您的“借用”参数?您可以通过添加 'bundle.containsKey("borrowed")' 来检查这是否返回 true?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 2018-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多