如何将图像点击数据从 RecycleAdapter 传递到 Fragment 接口,我在 MainActivity 中使用它来显示数据

How to pass data on image click from RecycleAdapter to Fragment interface, which I used in MainActivity to show data

我正在尝试将数据从 RecycleAdapter class 的 onClick 方法存档到 Fragment Class 并且那个 fragement class 有我在 MainActivity 中使用的接口得到那个数据。我在 Fragment class 中创建了一个 onButtonPressed() 方法,我在 recycleadapter onclick 方法中调用它来获取数据。 但是当我点击任何图像时,它显示 NullPointerException 错误:

04-17 03:24:56.376 6507-6545/com.santossingh.moviesinfoapp E/Surface: getSlotFromBufferLocked: unknown buffer: 0xf3d958e0
04-17 03:24:58.211 6507-6507/com.santossingh.moviesinfoapp E/AndroidRuntime: FATAL EXCEPTION: main
                                                                             Process: com.santossingh.moviesinfoapp, PID: 6507
                                                                             java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
                                                                                 at android.widget.Toast.<init>(Toast.java:102)
                                                                                 at android.widget.Toast.makeText(Toast.java:259)
                                                                                 at com.santossingh.moviesinfoapp.Fragments.Fragment_main.onButtonPressed(Fragment_main.java:176)
                                                                                 at com.santossingh.moviesinfoapp.Adapters.RecyclerAdapter$Holder.onClick(RecyclerAdapter.java:89)
                                                                                 at android.view.View.performClick(View.java:5198)
                                                                                 at android.view.View$PerformClick.run(View.java:21147)
                                                                                 at android.os.Handler.handleCallback(Handler.java:739)
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                 at android.os.Looper.loop(Looper.java:148)
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

这是我的代码 1) 主要 Activity class

public class MainActivity extends AppCompatActivity implements Fragment_main.OnFragmentInteractionListener{

    private Realm realm;
    private Results results;
    RecyclerAdapter recyclerAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this).build();
        Realm.setDefaultConfiguration(realmConfiguration);

    }

    @Override
    public void onFragmentInteraction(Results currentMovie) {
        if (currentMovie==null){
            Toast.makeText(this,"Null",Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this,"Hi ",Toast.LENGTH_SHORT).show();
        }
        DetailFragment detailFragment = (DetailFragment) getFragmentManager()
                .findFragmentById(R.id.Detail_container);

        if (detailFragment == null) {
            Toast.makeText(this,"single view",Toast.LENGTH_SHORT).show();

            Intent intent = new Intent(this, DetailActivity.class)
                .putExtra("movie_Id", currentMovie.getId())
                .putExtra("movie_Name", currentMovie.getTitle())
                .putExtra("poster_Path", currentMovie.getPoster_path())
                .putExtra("back_poster_Path", currentMovie.getBackdrop_path())
                .putExtra("release_Date", currentMovie.getRelease_date())
                .putExtra("users_Rating", currentMovie.getVote_average())
                .putExtra("overview", currentMovie.getOverview());
            startActivity(intent);

        } else {
            detailFragment.UpdateTabletUI(currentMovie);
        }
    }
}

2) Fragment_main class <* 更正后 *>************

public class Fragment_main extends Fragment implements RecyclerAdapter.GetDataFromAdapter {

    @Bind(R.id.recyclerView) RecyclerView recyclerView;
    private static final String STATE_MOVIES = "state_movies";
    private View rootView = null;
    private ServiceManager serviceManager;
    private RecyclerAdapter recyclerAdapter;
    private MovieResponse movieResponse;
    private List<Results> resultsList;

    private Results results;
    private OnFragmentInteractionListener mListener;
    private RecyclerAdapter.GetDataFromAdapter getDataFromAdapter;

    public Fragment_main() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelableArrayList(STATE_MOVIES, (ArrayList<? extends Parcelable>) resultsList);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.High_rated:
                if(item.isChecked()){
                    item.setChecked(false);
                }else{
                    item.setChecked(true);
                    makeService("TOP");
                    return true;
                }
            case R.id.most_Popular:
                if(item.isChecked()){
                    item.setChecked(false);
                }else{
                    item.setChecked(true);
                    makeService("POPULAR");
                    return true;
                }
            case R.id.favoriteList:
                if(item.isChecked()){
                    item.setChecked(false);
                }else{
                    item.setChecked(true);
                    Intent intent=new Intent(getActivity(), FavoriteActivity.class);
                    startActivity(intent);
                    return true;
                }
        }
        return super.onOptionsItemSelected(item);
    }

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

            ButterKnife.bind(this, rootView);
            resultsList=new ArrayList<Results>();
            configRecycleView();

            if (savedInstanceState==null){
                makeService("POPULAR");
            }else{
                resultsList=savedInstanceState.getParcelableArrayList(STATE_MOVIES);
                recyclerAdapter.addMovieList(resultsList);
            }
        return rootView;
    }

    private void makeService(String query){
        serviceManager = new ServiceManager();
        Call<MovieResponse> listCall;
            if (query=="TOP") {
                listCall= serviceManager.getJSONData().getTopMovies();
            }else{
                listCall= serviceManager.getJSONData().getPopMovies();
            }
            listCall.enqueue(new Callback<MovieResponse>() {
                @Override
                public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
                    if (response.isSuccessful()) {
                        Results[] results = response.body().getResults();
                        resultsList = new ArrayList<Results>(Arrays.asList(results));
                        recyclerAdapter.addMovieList(resultsList);
                        Toast.makeText(getActivity(), "Data Fatch", Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onFailure(Call<MovieResponse> call, Throwable t) {
                    Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
    }

    private void configRecycleView() {
       recyclerView.setHasFixedSize(true);
       recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
       recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),
               2));
       recyclerAdapter = new RecyclerAdapter(getActivity(),getDataFromAdapter
       );
       recyclerView.setAdapter(recyclerAdapter);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onCurrentMovie(Results currentMovie) {
        mListener.onFragmentInteraction(currentMovie);
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Results result);
    }

}

3) 回收适配器 class

public class RecyclerAdapter 扩展 RecyclerView.Adapter{ 私有列表 resultsList=new ArrayList(); 私有视图 rcView; 私有上下文上下文; int 介词;

GetDataFromAdapter callback;
private Results currentMovie;

public interface GetDataFromAdapter{
    void onCurrentMovie(Results currentMovie);
}

public RecyclerAdapter(Context context, GetDataFromAdapter callback) {
    this.context=context;
    this.callback = callback;
}

@Override
// create View object and pass it on Holder class constructor
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
    rcView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_image_fragment, parent, false);
    return new Holder(rcView);
}

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

public void addMovieList(List<Results> movie){
    resultsList=movie;
    notifyDataSetChanged();
}

@Override
public void onBindViewHolder(Holder holder, int position) {
    Results currentMovie = resultsList.get(position);
    Picasso.with(holder.imageView.getContext())
            .load(Constant.HTTP.IMAGE_BASE_URL + currentMovie.getPoster_path())
            .resize(240, 330)
            .placeholder(R.drawable.placeholder)
            .error(R.drawable.error)
            .into(holder.imageView);

    // animation part ----------------
    if (position>preposition){
        AnimationUtil.animate(holder, true);
    }else {
        AnimationUtil.animate(holder,false);
    }
    preposition=position;
}

public class Holder extends RecyclerView.ViewHolder implements View.OnClickListener{
    private ImageView imageView;

    public Holder(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);
        imageView=(ImageView)itemView.findViewById(R.id.imageView);
    }

    @Override
    public void onClick(View v) {
        int position = getAdapterPosition();
        currentMovie=resultsList.get(position);
        Toast.makeText(v.getContext(),currentMovie.getTitle(),Toast.LENGTH_SHORT).show();
        callback.onCurrentMovie(currentMovie);
    }
}

} 更正后它再次显示 NullPointerException : 这是错误

04-17 04:19:21.832 7118-7147/com.santossingh.moviesinfoapp E/Surface: getSlotFromBufferLocked: unknown buffer: 0xdefa22a0
04-17 04:19:22.633 7118-7118/com.santossingh.moviesinfoapp E/AndroidRuntime: FATAL EXCEPTION: main
                                                                             Process: com.santossingh.moviesinfoapp, PID: 7118
                                                                             java.lang.NullPointerException: Attempt to invoke interface method 'void com.santossingh.moviesinfoapp.Adapters.RecyclerAdapter$GetDataFromAdapter.onCurrentMovie(com.santossingh.moviesinfoapp.DB.Models.Results)' on a null object reference
                                                                                 at com.santossingh.moviesinfoapp.Adapters.RecyclerAdapter$Holder.onClick(RecyclerAdapter.java:92)
                                                                                 at android.view.View.performClick(View.java:5198)
                                                                                 at android.view.View$PerformClick.run(View.java:21147)
                                                                                 at android.os.Handler.handleCallback(Handler.java:739)
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                 at android.os.Looper.loop(Looper.java:148)
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

更正后,在模拟器中显示了一个错误并且图像没有显示,这是模拟器的图片:

enter image description here

04-17 04:54:16.961 23492-23520/com.santossingh.moviesinfoapp E/Surface: getSlotFromBufferLocked: unknown buffer: 0xeb08a7e0

两个class代码在这里: 片段class

public class Fragment_main extends Fragment implements RecyclerAdapter.GetDataFromAdapter {

    @Bind(R.id.recyclerView) RecyclerView recyclerView;
    private static final String STATE_MOVIES = "state_movies";
    private View rootView = null;
    private ServiceManager serviceManager;
    private RecyclerAdapter recyclerAdapter;
    private MovieResponse movieResponse;
    private List<Results> resultsList;

    private Results results;
    private OnFragmentInteractionListener mListener;
    private RecyclerAdapter.GetDataFromAdapter getDataFromAdapter;

    public Fragment_main() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelableArrayList(STATE_MOVIES, (ArrayList<? extends Parcelable>) resultsList);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.High_rated:
                if(item.isChecked()){
                    item.setChecked(false);
                }else{
                    item.setChecked(true);
                    makeService("TOP");
                    return true;
                }
            case R.id.most_Popular:
                if(item.isChecked()){
                    item.setChecked(false);
                }else{
                    item.setChecked(true);
                    makeService("POPULAR");
                    return true;
                }
            case R.id.favoriteList:
                if(item.isChecked()){
                    item.setChecked(false);
                }else{
                    item.setChecked(true);
                    Intent intent=new Intent(getActivity(), FavoriteActivity.class);
                    startActivity(intent);
                    return true;
                }
        }
        return super.onOptionsItemSelected(item);
    }

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

            ButterKnife.bind(this, rootView);
            resultsList=new ArrayList<Results>();
            configRecycleView();

            if (savedInstanceState==null){
                makeService("POPULAR");
            }else{
                resultsList=savedInstanceState.getParcelableArrayList(STATE_MOVIES);
                recyclerAdapter.addMovieList(resultsList);
            }
        return rootView;
    }

    private void makeService(String query){
        serviceManager = new ServiceManager();
        Call<MovieResponse> listCall;
            if (query=="TOP") {
                listCall= serviceManager.getJSONData().getTopMovies();
            }else{
                listCall= serviceManager.getJSONData().getPopMovies();
            }
            listCall.enqueue(new Callback<MovieResponse>() {
                @Override
                public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
                    if (response.isSuccessful()) {
                        Results[] results = response.body().getResults();
                        resultsList = new ArrayList<Results>(Arrays.asList(results));
                        recyclerAdapter.addMovieList(resultsList);
                        Toast.makeText(getActivity(), "Data Fatch", Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onFailure(Call<MovieResponse> call, Throwable t) {
                    Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
    }

    private void configRecycleView() {
       recyclerView.setHasFixedSize(true);
       recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
       recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),
               2));
       recyclerAdapter = new RecyclerAdapter(getActivity(),getDataFromAdapter);
       recyclerView.setAdapter(recyclerAdapter);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onCurrentMovie(Results currentMovie) {
        mListener.onFragmentInteraction(currentMovie);
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Results result);
    }

}

回收适配器class

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.Holder>{
    private List<Results> resultsList=new ArrayList<Results>();
    private View rcView;
    private Context context;
    int preposition;

    GetDataFromAdapter callback;
    private Results currentMovie;

    public interface GetDataFromAdapter{
        void onCurrentMovie(Results currentMovie);
    }

    public RecyclerAdapter(Context context, GetDataFromAdapter callback) {
        this.context=context;
        this.callback = callback;
    }

    @Override
    // create View object and pass it on Holder class constructor
    public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
        rcView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.list_image_fragment, parent, false);
        return new Holder(rcView, callback);
    }

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

    public void addMovieList(List<Results> movie){
        resultsList=movie;
        notifyDataSetChanged();
    }

    @Override
    public void onBindViewHolder(Holder holder, int position) {
        Results currentMovie = resultsList.get(position);
        Picasso.with(holder.imageView.getContext())
                .load(Constant.HTTP.IMAGE_BASE_URL + currentMovie.getPoster_path())
                .resize(240, 330)
                .placeholder(R.drawable.placeholder)
                .error(R.drawable.error)
                .into(holder.imageView);

        // animation part ----------------
        if (position>preposition){
            AnimationUtil.animate(holder, true);
        }else {
            AnimationUtil.animate(holder,false);
        }
        preposition=position;
    }

    public class Holder extends RecyclerView.ViewHolder implements View.OnClickListener{
        private ImageView imageView;
        private GetDataFromAdapter callback;

        public Holder(View itemView, GetDataFromAdapter callback) {
            super(itemView);
            itemView.setOnClickListener(this);
            this.callback=callback;
            imageView=(ImageView)itemView.findViewById(R.id.imageView);
        }

        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();
            currentMovie=resultsList.get(position);
            Toast.makeText(v.getContext(),currentMovie.getTitle(),Toast.LENGTH_SHORT).show();
            callback.onCurrentMovie(currentMovie);
        }
    }

}

Fragment class 方法和 RecycleAdapter onclick 方法中再次出现 NullException。

I test it via toast. Data comes in Fragement but erro shows when it send from fragment interface mListener to main Activity which called in callback method.

@Override
    public void onCurrentMovie(Results currentMovie) {
        mListener.onFragmentInteraction(currentMovie);
    }

和 RecycleAdapter class onclick 方法行

   callback.onCurrentMovie(currentMovie);

错误logcat:

FATAL EXCEPTION: main
                                                                             java.lang.NullPointerException
                                                                                 at com.santossingh.moviesinfoapp.Fragments.Fragment_main.onCurrentMovie(Fragment_main.java:173)
                                                                                 at com.santossingh.moviesinfoapp.Adapters.RecyclerAdapter$Holder.onClick(RecyclerAdapter.java:93)
                                                                                 at android.view.View.performClick(View.java:4084)
                                                                                 at android.view.View$PerformClick.run(View.java:16966)
                                                                                 at android.os.Handler.handleCallback(Handler.java:615)
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:92)
                                                                                 at android.os.Looper.loop(Looper.java:137)
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:4745)
                                                                                 at java.lang.reflect.Method.invokeNative(Native Method)
                                                                                 at java.lang.reflect.Method.invoke(Method.java:511)
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
                                                                                 at dalvik.system.NativeStart.main(Native Method)

你做错的是:

fragment_main=new Fragment_main();
fragment_main.onButtonPressed(currentMovie);

创建 fragment 的新实例。此实例如何引用正在显示的实例?

您可以通过如下所述的接口获取数据:

在适配器中定义一个interface

public interface GetDataFromAdapter{
    void onCurrentMovie(Results currentMovie);
}

fragment 中实现并覆盖接口方法:

public class Fragment_main extends Fragment implements RecyclerAdapter.GetDataFromAdapter{
}

并像这样创建适配器实例:

recyclerAdapter = new RecyclerAdapter(getActivity(), Fragment_main.this);
recyclerView.setAdapter(recyclerAdapter);

现在像这样更改适配器的构造函数:

GetDataFromAdapter callback;
private Results currentMovie;

public RecyclerAdapter(Context context, GetDataFromAdapter callback) {
    this.context=context;
    this.callback = callback;
}

现在,由于您正在传递来自 ViewHolder 的数据,因此您必须将 callback 引用传递给它。

public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
   rcView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.list_image_fragment, parent, false);
   return new Holder(rcView, callback);
}

因此 Holder 的构造函数如下:

private ImageView imageView;
private GetDataFromAdapter callback;

public Holder(View itemView, GetDataFromAdapter callback) {
    super(itemView);
    this.callback = callback;
    itemView.setOnClickListener(this);
    imageView=(ImageView)itemView.findViewById(R.id.imageView);
}

像这样将数据发送到片段:

@Override
public void onClick(View v) {
    int position = getAdapterPosition();
    currentMovie=resultsList.get(position);

    callback.onCurrentMovie(currentMovie);
}

片段中的覆盖方法将接收 currentMovie 个对象。