获取空指针异常 - 使用接口将数据从适配器传递到子片段
Getting Null Pointer Exception - Using an Interface to Pass Data from an Adapter to a Sub-fragment
我有一个 Adapter
和一个 Sub-Fragment
。我正在使用一个接口将数据从 Adapter
传递到 Sub-Fragment
。我遇到的问题是我一直收到 Null Pointer Exception
。我已经阅读了此处与该问题相关的各种帖子,但无法弄清楚我哪里出错了。我在 'passAdapterVariable.passAdapterVariable(mname)' 行得到了 NPE。根据我所阅读的内容,我怀疑这可能是因为我没有正确初始化 passAdapterVariable。我已经尝试根据其他示例以几种不同的方式初始化它,但我一直收到 NPE。
这是适配器
public class MatchAdapter extends RecyclerView.Adapter<MatchAdapter.MatchViewHolder> {
//declaration of variables
private Fragment fragment;
private FragmentManager fragmentManager;
private DiscoverPage discoverPage;
private Context context;
private int size;
private int mposition;
private TextView txt_matchname;
private ImageView img_matchpic;
List<String> maImg = new ArrayList<>();
private String mname;
PassAdapterVariable passAdapterVariable;
public interface PassAdapterVariable {
void passAdapterVariable(String mname);
}
//the constructor
public MatchAdapter(List<String> maImg, int size, Context context, DiscoverPage discoverPage){//, PassAdapterVariable passAdapterVariable) {
this.maImg = maImg;
this.context = context;
this.discoverPage = discoverPage;
this.size = size;
//this.passAdapterVariable = (PassAdapterVariable)context;
}
public MatchAdapter(String mname, Context context) {
this.context = context;
this.passAdapterVariable = (PassAdapterVariable)context;
}
//PassAdapterVariable passAdapterVariable = (PassAdapterVariable) context;
@Override
public MatchAdapter.MatchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.match_items, parent, false);
MatchViewHolder matchViewHolder = new MatchViewHolder(view, maImg, discoverPage);
return matchViewHolder;
}
@Override
public void onBindViewHolder(MatchViewHolder holder, int position) {
Picasso.with(context).load(maImg.get(position)).into(holder.img_match);
holder.setIsRecyclable(false);
}
@Override
public int getItemCount() {
return maImg.size();
}
//viewholder class
public class MatchViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private static final String TAG = "error";
//declare variables
private DiscoverPage discoverPage;
private ImageView img_match;
//ViewHolder constructor
public MatchViewHolder(View itemView, final List<String> maImg, final DiscoverPage discoverPage) {
super(itemView);
//initialize variables inside the viewholder constructor
this.discoverPage = discoverPage;
img_match = (ImageView) itemView.findViewById(R.id.img_match);
txt_matchname = (TextView) itemView.findViewById(R.id.txt_matchname);
img_matchpic = (ImageView) itemView.findViewById(R.id.img_matchpic);
//set click listener for the img_match
img_match.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (view == img_match) {
//discoverPage.isHidden();
Fragment currentFragment;
fragment = new ClickedMatch();
fragmentManager = ((AppCompatActivity) context).getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(android.R.id.content, fragment);
transaction.addToBackStack("DiscoverPage");
if ((currentFragment = ((AppCompatActivity) context).getSupportFragmentManager().findFragmentById(R.id.main_container)) != null) {
transaction.hide(currentFragment);
}
else {
transaction.commit();
}
mname = maImg.get(getAdapterPosition());
mposition = getAdapterPosition();
mname = maImg.get(mposition);
passAdapterVariable.passAdapterVariable(mname);
}
}
}
}
这是子片段
public class ClickedMatch extends Fragment implements MatchAdapter.PassAdapterVariable{
//declare variables
private Toolbar toolbar;
private TextView txt_matchname;
private TextView txt_matchprice;
private ImageView img_matchpic;
private String mname;
private String imgmatch;
List<String> maImg = new ArrayList<>();
int size;
Context context;
DiscoverPage discoverPage;
private String pname;
private int i;
MatchAdapter.PassAdapterVariable passAdapterVariable;
public ClickedMatch() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_clicked_match, container, false);
//initialize variables
toolbar = (Toolbar) view.findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);//set toolbar as action bar
txt_matchname = (TextView)view.findViewById(R.id.txt_matchname);
img_matchpic = (ImageView)view.findViewById(R.id.img_matchpic);
//setHasOptionsMenu(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().onBackPressed();
}
});
if(((AppCompatActivity)getActivity()).getSupportActionBar()!= null){
((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayShowHomeEnabled(true);
((AppCompatActivity)getActivity()).getSupportActionBar().setHomeButtonEnabled(true);
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("");
}
// MatchAdapter matAdapter = new MatchAdapter(maImg, size, context, discoverPage,
//passAdapterVariable);
// matAdapter.passAdapterVariable = this;
//passAdapterVariable.passAdapterVariable(mname);
//txt_matchname.setText(pname);
MatchAdapter matAdapter = new MatchAdapter(pname, getContext());
matAdapter.passAdapterVariable = this;
passAdapterVariable(pname);
txt_matchname.setText(pname);
return view;
}
@Override
public void passAdapterVariable(String mname) {
this.pname = mname;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
this.getActivity().finish();
}
return super.onOptionsItemSelected(item);
}
}
这是错误日志
08-13 21:53:49.341 12852-12852/com.test.jack E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test.jack, PID: 12852
java.lang.NullPointerException: Attempt to invoke interface method 'void com.test.jack.MatchAdapter$PassAdapterVariable.passAdapterVariable(java.lang.String)' on a null object reference
at com.test.jack.MatchAdapter$MatchViewHolder.onClick(MatchAdapter.java:138)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
为了添加更多上下文,我有一个主 activity(UserMainPage)。底部导航菜单选择器用片段 (DiscoverPage) 替换了 UserMainPage。
DiscoverPage 调用适配器(MatchAdapter)。单击 DiscoverPage 上的按钮会用子片段 (ClickedMatch) 替换 DiscoverPage。
我正在尝试将一个变量从 MatchAdapter 传递到 ClickedMatch。
当您调用 passAdapterVariable.passAdapterVariable(mname);
时,看起来字符串 "mname" 为空
要么你的List maImg是空的|| null 或提供的适配器位置错误。
尝试记录
Log.d(TAG, "pos: " + getAdapterPosition());
mname = maImg.get(getAdapterPosition());
Log.d(TAG, "name: " + mname);
PassAdapterVariable passAdapterVariable = (PassAdapterVariable) context;
只是你适配器中的声明+赋值语句class。此时,context 为空。
变量上下文仅在您的构造函数中分配。在分配 context 之后分配 passAdapterVariable
public MatchAdapter(List<String> maImg, int size, Context context, DiscoverPage discoverPage) {
this.maImg = maImg;
this.context = context;
this.discoverPage = discoverPage;
this.size = size;
passAdapterVariable = (PassAdapterVariable) context;
}
You can add Context parameter in constructor of Adapter with String as
public MatchAdapter(String mname, Context context) {
this.context = context;
}
Now get the context from Fragment as
MatchAdapter matAdapter = new MatchAdapter(pname, getActivity());
matAdapter.passAdapterVariable = this;
passAdapterVariable(pname);
txt_matchname.setText(tname);
return view;
MatchAdapter 内部------
在将作为
工作的构造函数中将实例添加到您的接口
{
DataInterface passInterface;
Context context;
public MatchAdapter(String mname, Context context1, DataPass pass) {
this.passAdapterVariable = mname;
this.context = context1;
this.passInterface = pass;
}
}
现在在调用适配器时获取该接口的实例
{
MatchAdapter matAdapter = new MatchAdapter(pname, getActivity(),this);
}
我能够使用 Bundle
将数据从适配器传递到子片段。
我修改了我的代码如下:
在我添加的适配器中:
fragment = new ClickedMatch();
Bundle bundle = new Bundle();
bundle.putString("matchname",mname);
fragment.setArguments(bundle);
...
transaction.commit();
在我的子片段中我添加了:
Bundle bundle = this.getArguments();
if(bundle != null){
pname = bundle.getString("matchname");
}
不需要使用接口。根据我的研究,我认为(我可能是错的)创建一个接口然后实现它在片段之间通信而不是在适配器和子片段之间通信时更好用。
我有一个 Adapter
和一个 Sub-Fragment
。我正在使用一个接口将数据从 Adapter
传递到 Sub-Fragment
。我遇到的问题是我一直收到 Null Pointer Exception
。我已经阅读了此处与该问题相关的各种帖子,但无法弄清楚我哪里出错了。我在 'passAdapterVariable.passAdapterVariable(mname)' 行得到了 NPE。根据我所阅读的内容,我怀疑这可能是因为我没有正确初始化 passAdapterVariable。我已经尝试根据其他示例以几种不同的方式初始化它,但我一直收到 NPE。
这是适配器
public class MatchAdapter extends RecyclerView.Adapter<MatchAdapter.MatchViewHolder> {
//declaration of variables
private Fragment fragment;
private FragmentManager fragmentManager;
private DiscoverPage discoverPage;
private Context context;
private int size;
private int mposition;
private TextView txt_matchname;
private ImageView img_matchpic;
List<String> maImg = new ArrayList<>();
private String mname;
PassAdapterVariable passAdapterVariable;
public interface PassAdapterVariable {
void passAdapterVariable(String mname);
}
//the constructor
public MatchAdapter(List<String> maImg, int size, Context context, DiscoverPage discoverPage){//, PassAdapterVariable passAdapterVariable) {
this.maImg = maImg;
this.context = context;
this.discoverPage = discoverPage;
this.size = size;
//this.passAdapterVariable = (PassAdapterVariable)context;
}
public MatchAdapter(String mname, Context context) {
this.context = context;
this.passAdapterVariable = (PassAdapterVariable)context;
}
//PassAdapterVariable passAdapterVariable = (PassAdapterVariable) context;
@Override
public MatchAdapter.MatchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.match_items, parent, false);
MatchViewHolder matchViewHolder = new MatchViewHolder(view, maImg, discoverPage);
return matchViewHolder;
}
@Override
public void onBindViewHolder(MatchViewHolder holder, int position) {
Picasso.with(context).load(maImg.get(position)).into(holder.img_match);
holder.setIsRecyclable(false);
}
@Override
public int getItemCount() {
return maImg.size();
}
//viewholder class
public class MatchViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private static final String TAG = "error";
//declare variables
private DiscoverPage discoverPage;
private ImageView img_match;
//ViewHolder constructor
public MatchViewHolder(View itemView, final List<String> maImg, final DiscoverPage discoverPage) {
super(itemView);
//initialize variables inside the viewholder constructor
this.discoverPage = discoverPage;
img_match = (ImageView) itemView.findViewById(R.id.img_match);
txt_matchname = (TextView) itemView.findViewById(R.id.txt_matchname);
img_matchpic = (ImageView) itemView.findViewById(R.id.img_matchpic);
//set click listener for the img_match
img_match.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (view == img_match) {
//discoverPage.isHidden();
Fragment currentFragment;
fragment = new ClickedMatch();
fragmentManager = ((AppCompatActivity) context).getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(android.R.id.content, fragment);
transaction.addToBackStack("DiscoverPage");
if ((currentFragment = ((AppCompatActivity) context).getSupportFragmentManager().findFragmentById(R.id.main_container)) != null) {
transaction.hide(currentFragment);
}
else {
transaction.commit();
}
mname = maImg.get(getAdapterPosition());
mposition = getAdapterPosition();
mname = maImg.get(mposition);
passAdapterVariable.passAdapterVariable(mname);
}
}
}
}
这是子片段
public class ClickedMatch extends Fragment implements MatchAdapter.PassAdapterVariable{
//declare variables
private Toolbar toolbar;
private TextView txt_matchname;
private TextView txt_matchprice;
private ImageView img_matchpic;
private String mname;
private String imgmatch;
List<String> maImg = new ArrayList<>();
int size;
Context context;
DiscoverPage discoverPage;
private String pname;
private int i;
MatchAdapter.PassAdapterVariable passAdapterVariable;
public ClickedMatch() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_clicked_match, container, false);
//initialize variables
toolbar = (Toolbar) view.findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);//set toolbar as action bar
txt_matchname = (TextView)view.findViewById(R.id.txt_matchname);
img_matchpic = (ImageView)view.findViewById(R.id.img_matchpic);
//setHasOptionsMenu(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().onBackPressed();
}
});
if(((AppCompatActivity)getActivity()).getSupportActionBar()!= null){
((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayShowHomeEnabled(true);
((AppCompatActivity)getActivity()).getSupportActionBar().setHomeButtonEnabled(true);
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("");
}
// MatchAdapter matAdapter = new MatchAdapter(maImg, size, context, discoverPage,
//passAdapterVariable);
// matAdapter.passAdapterVariable = this;
//passAdapterVariable.passAdapterVariable(mname);
//txt_matchname.setText(pname);
MatchAdapter matAdapter = new MatchAdapter(pname, getContext());
matAdapter.passAdapterVariable = this;
passAdapterVariable(pname);
txt_matchname.setText(pname);
return view;
}
@Override
public void passAdapterVariable(String mname) {
this.pname = mname;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
this.getActivity().finish();
}
return super.onOptionsItemSelected(item);
}
}
这是错误日志
08-13 21:53:49.341 12852-12852/com.test.jack E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test.jack, PID: 12852
java.lang.NullPointerException: Attempt to invoke interface method 'void com.test.jack.MatchAdapter$PassAdapterVariable.passAdapterVariable(java.lang.String)' on a null object reference
at com.test.jack.MatchAdapter$MatchViewHolder.onClick(MatchAdapter.java:138)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
为了添加更多上下文,我有一个主 activity(UserMainPage)。底部导航菜单选择器用片段 (DiscoverPage) 替换了 UserMainPage。
DiscoverPage 调用适配器(MatchAdapter)。单击 DiscoverPage 上的按钮会用子片段 (ClickedMatch) 替换 DiscoverPage。
我正在尝试将一个变量从 MatchAdapter 传递到 ClickedMatch。
当您调用 passAdapterVariable.passAdapterVariable(mname);
时,看起来字符串 "mname" 为空要么你的List maImg是空的|| null 或提供的适配器位置错误。
尝试记录
Log.d(TAG, "pos: " + getAdapterPosition());
mname = maImg.get(getAdapterPosition());
Log.d(TAG, "name: " + mname);
PassAdapterVariable passAdapterVariable = (PassAdapterVariable) context;
只是你适配器中的声明+赋值语句class。此时,context 为空。
变量上下文仅在您的构造函数中分配。在分配 context 之后分配 passAdapterVariable
public MatchAdapter(List<String> maImg, int size, Context context, DiscoverPage discoverPage) {
this.maImg = maImg;
this.context = context;
this.discoverPage = discoverPage;
this.size = size;
passAdapterVariable = (PassAdapterVariable) context;
}
You can add Context parameter in constructor of Adapter with String as
public MatchAdapter(String mname, Context context) {
this.context = context;
}
Now get the context from Fragment as
MatchAdapter matAdapter = new MatchAdapter(pname, getActivity());
matAdapter.passAdapterVariable = this;
passAdapterVariable(pname);
txt_matchname.setText(tname);
return view;
MatchAdapter 内部------ 在将作为
工作的构造函数中将实例添加到您的接口{
DataInterface passInterface;
Context context;
public MatchAdapter(String mname, Context context1, DataPass pass) {
this.passAdapterVariable = mname;
this.context = context1;
this.passInterface = pass;
}
}
现在在调用适配器时获取该接口的实例
{
MatchAdapter matAdapter = new MatchAdapter(pname, getActivity(),this);
}
我能够使用 Bundle
将数据从适配器传递到子片段。
我修改了我的代码如下:
在我添加的适配器中:
fragment = new ClickedMatch();
Bundle bundle = new Bundle();
bundle.putString("matchname",mname);
fragment.setArguments(bundle);
...
transaction.commit();
在我的子片段中我添加了:
Bundle bundle = this.getArguments();
if(bundle != null){
pname = bundle.getString("matchname");
}
不需要使用接口。根据我的研究,我认为(我可能是错的)创建一个接口然后实现它在片段之间通信而不是在适配器和子片段之间通信时更好用。