2

我有一个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) 

要添加更多的上下文,我有一个主要活动(UserMainPage)。底部导航菜单选择器用一个片段(DiscoverPage)替换UserMainPage。

DiscoverPage调用适配器(MatchAdapter)。点击发现页面上的按钮用一个子片段替换DiscoverPage(ClickedMatch)。

我想将MatchAdapter的变量传递给ClickedMatch。

+1

您的语境在语句中为空PassAdapterVariable passAdapterVariable =(PassAdapterVariable)context ;,将其移至适配器类构造函数。 – darwin

+0

我移动了PassAdapterVariable passAdapterVariable =(passAdapterVariable)上下文。我有两个构造函数(不知道这是不是好习惯),当我把它放在第二个构造函数时,我得到了相同的NPE。当我将它放在第一个构造函数中时,程序崩溃,并且我收到错误消息User Main Page(这是主要活动)不能转换为MatchAdapter.PassAdapterVariable。 @darwin –

+0

did你在你的Activity中实现了PassAdapterVariable接口吗? – darwin

回答

0

我能找到没有从那些谁评论或提供洞察到这一问题,并只会展示他们的无能和浪费我的时间帮助解决。

我能够使用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"); 
} 

没有必要使用一个接口。根据我所研究的内容,我认为(我可能错了)创建接口并实现它的时候,最好在片段之间进行通信时使用,而不是在适配器和子片段之间进行通信。

0

当您调用passAdapterVariable.passAdapterVariable(mname)时,看起来像字符串“mname”为null。

要么你是列表maImg是空的|| null或提供的适配器位置错误。

尝试登录

  Log.d(TAG, "pos: " + getAdapterPosition()); 
      mname = maImg.get(getAdapterPosition()); 
      Log.d(TAG, "name: " + mname); 
+0

列表maImg不为空。按照建议实施日志,并且得到值08-13 23:20:59.943 29966-29966/com.test.jack D /错误:pos:0 08-13 23:20:59.943 29966-29966/com.test。杰克D /错误:名称:https://firebasestorage.googleapis.com/v0/b/jack-... @ gekn76 –

0
PassAdapterVariable passAdapterVariable = (PassAdapterVariable) 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; 

    } 
+0

我分配了上下文后的passAdapterVariable,我仍然得到NPE。 @Arun Shankar –

+0

你可以发布更改后的代码吗?让我编辑我的答案,以显示我的意思是更好 –

+0

已更改的代码已发布。 @Arun Shankar –

0
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; 
+0

尝试建议。我仍然得到NPE。我发布了更新的代码并添加了一些更多的上下文问题。@Sushil Chaudhary –

0

内MatchAdapter ------ 添加实例在构造你的界面,将工作作为

{ 
DataInterface passInterface; 
Context context; 
public MatchAdapter(String mname, Context context1, DataPass pass) { 

     this.passAdapterVariable = mname; 
     this.context = context1; 
     this.passInterface = pass; 
    } 
} 

现在获取该接口的实例,而c阿灵适配器

{ 

MatchAdapter matAdapter = new MatchAdapter(pname, getActivity(),this); 
} 
+0

当我添加DataInterace passInterface I我不能写“this.passadapterVariable = mname”,它们是不兼容的类型@Sushil Chaudhary –

+0

DataInterface是你创建的接口写入你为接口给出的类名并初始化了passAdapterVariable之前构造函数为 String passAdapterVariable;使用它 –

+0

检查出来@RookyCoder –