如何使用RecyclerView打开一个新片段

时间:2016-03-29 13:29:07

标签: android-fragments android-recyclerview

我正在尝试创建一个类似于地方选择器的应用程序,这意味着您写下了比萨饼或汉堡等产品,并且您可以获得周围有披萨或汉堡的所有地方。 现在我在我的片段中使用RecyclerView,我也有Map片段 当您单击RV中的项目时,它将使用地图片段在地图上显示其位置。 我的问题是,当我点击recyclerview中的某个项目时,我会得到nullpointerexception 这是我的第一个片段的代码

public class PlacesFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> , AdapterView.OnItemClickListener{

ClickListener listener;
static Places places;
PlacesAdapter adapter;
public FragmentManager fm;
MyMapFragment mapFragment;
Cursor cursor;

public PlacesFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View myFragView= inflater.inflate(R.layout.fragment_places, container, false);


    RecyclerView rv= (RecyclerView)myFragView.findViewById(R.id.placesRecyclerView);
    //this create the line beetween every list to do so i have import to the build gradle a flexible divider
    rv.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).color(Color.BLACK).build());

    cursor = getActivity().getContentResolver().query(CONTENT_URI, null, null, null, null);


    adapter= new PlacesAdapter(cursor, getActivity());
    rv.setAdapter(adapter);
    adapter.notifyItemRangeChanged(cursor.getPosition(), cursor.getCount());
    adapter.notifyDataSetChanged();

    rv.setLayoutManager(new LinearLayoutManager(getActivity()));
    rv.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), rv, new ClickListener() {

                @Override
                public void onPlaceClick(String  latlng) {
                    //when i click on a place it will go to the map fragment
                 //   Toast.makeText(getActivity(), "on click" + position, Toast.LENGTH_LONG).show();
                /*    FragmentManager fm = getFragmentManager();

                    // get the map object from the fragment:
                    mapFragment = MyMapFragment.newInstance(places);

                    FragmentTransaction ft = fm.beginTransaction();


                    ft.replace(R.id.fragmantContainer, mapFragment, "map");
                    ft.addToBackStack(null);

                    ft.commit();*/

                }
            })
    );

 //   getLoaderManager().initLoader(1, null,);

    return myFragView;
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    try {
        listener =  (ClickListener)context;
    } catch (ClassCastException e) {
        throw new ClassCastException("context " + context.toString()
                + "must implement PlacesFragmantListener!");
    }
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    //  CursorLoader c=getContext().getContentResolver().query(PlacesContract.Places.CONTENT_URI, null, null,null, null);

    return new CursorLoader(getActivity(),CONTENT_URI,  null, null,null, null );
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {


}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
 }


@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {


}



public static interface PlacesFragmantListener {
   public  void onLocationSelected(Places places);
}

 class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{

    private GestureDetector gestureDetector;
    private ClickListener clickListener;
    MyMapFragment mapFragment;

    public RecyclerTouchListener(Context context, RecyclerView recyclerView, ClickListener clickListener){
        gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener(){
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                super.onLongPress(e);
            }
        });
        this.clickListener = clickListener;
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {

        View child = rv.findChildViewUnder(e.getX(),e.getY());


        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        Log.d("PlaceAdapter", "onTouchEvent"+e);
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
   }

 }

这是我的地图片段

public class MyMapFragment extends Fragment {

public MyMapFragment(){

}
public static MyMapFragment newInstance(Places places) {}


    if (places == null) {
        places = new Places(0,"no Location selected","","", "");
    }

    // the arguments to pass
    Bundle args = new Bundle();
    args.putString("location", places.getLocation());

    args.putDouble("lat", location.getLat());
    args.putDouble("lon", location.getLon());

    MyMapFragment mapFragmant = new MyMapFragment();

    mapFragmant.setArguments(args);

    return mapFragmant;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.mapfragment, container, false);

    Bundle b=getArguments();
    String latlng=   b.getString("location");
    Log.d("fragment...", latlng);



    String[] latlongarr= latlng.split(",");

    double lat= Double.parseDouble(latlongarr[0]);
    double lon= Double.parseDouble(latlongarr[1]);


    FragmentManager fm = getFragmentManager();
    MapFragment mapFragment = (MapFragment) fm.findFragmentById(R.id.map);
    // get the map object from the fragment:

    GoogleMap map = mapFragment.getMap();

    if(map!= null) {
        // setup the map type:
        map.setMapType(GoogleMap.MAP_TYPE_HYBRID);

        // setup map position and zoom
        LatLng position = new LatLng(b.getDouble("lat"), b.getDouble("lon"));
        CameraUpdate update = CameraUpdateFactory.newLatLngZoom(position, 15);
        map.moveCamera(update);
    }
    return view;
}
}

这是我的适配器

public class PlacesAdapter extends    RecyclerView.Adapter<PlacesAdapter.PlaceHolder> {

private Cursor cursor;
private Context context;
private static TextView placeName, address, distance, url;
public  static ImageView imgplace;
public  static PlaceHolder.ClickListener clickListener;
private  static Places place;
private DataSetObserver mDataSetObserver;
MyMapFragment mapFragment;
private boolean mDataValid;
ClickListener listener;



public PlacesAdapter(Cursor cursor, Context context) {
    this.context = context;
    this.cursor = cursor;
    mDataSetObserver = new NotifyingDataSetObserver();
    if (cursor != null) {
        cursor.registerDataSetObserver(mDataSetObserver);
    }

}

 @Override
 public PlaceHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    //   cursor.setNotificationUri(context.getContentResolver(), CONTENT_URI);
    LayoutInflater inflater = LayoutInflater.from(context);
    View myView = inflater.inflate(R.layout.single_place, parent, false);


    PlaceHolder placeHolder = new PlaceHolder(myView, new PlaceHolder.PlacesFragmantListener() {
        @Override
        public void onLocationSelected(Places places) {

        }
    });

    return placeHolder;
}

@Override
public void setHasStableIds(boolean hasStableIds) {
    super.setHasStableIds(true);
}

@Override
public void onBindViewHolder(PlacesAdapter.PlaceHolder holder, final int position) {

    if (cursor.moveToPosition(position)) {


        int column_number = cursor.getColumnIndex(PLACES_NAME);
        String name = cursor.getString(column_number);
        placeName.setText(name);

        int column_number2 = cursor.getColumnIndex(PLACES_ADDRESS);
        String adr = cursor.getString(column_number2);
        address.setText(adr);

        int column_number3 = cursor.getColumnIndex(PLACES_DISTANEC);
        String dis = cursor.getString(column_number3);
        distance.setText(dis);

        int column_number4 = cursor.getColumnIndex(PLACE_PHOTO);
        String photo = cursor.getString(column_number4);

        if(!photo.equals(""))
        {
            GoogleAccess.myImageDownloader loader= new GoogleAccess.myImageDownloader(imgplace);
            loader.execute(photo);
        }

    }
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(context, "Item click at " + position, Toast.LENGTH_LONG).show();
            if(cursor.moveToPosition(position))
            {
                String latlong= cursor.getString(cursor.getColumnIndex(PlacesDbconstanst.CurrentPlaces.PLACES_DISTANEC));

                listener.onPlaceClick(latlong);
            }

        }
    });

}

public void setClickListener(PlaceHolder.ClickListener clickListener){
         this.clickListener = clickListener;
}

@Override
public int getItemCount() {
    return cursor.getCount();
}



public static class PlaceHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    PlacesFragmantListener listener;

    public PlaceHolder(View itemView, PlacesFragmantListener placesFragmantListener) {
        super(itemView);
        listener = placesFragmantListener;
        placeName = (TextView) itemView.findViewById(R.id.placeNametextView);
        address = (TextView) itemView.findViewById(R.id.addressTextView);
        distance = (TextView) itemView.findViewById(R.id.distanceTextView);
        imgplace = (ImageView) itemView.findViewById(R.id.placesImageViewId);
        imgplace.setOnClickListener(this);
        itemView.setOnClickListener(this);


    }
    RecyclerView rv;
    @Override
    public void onClick(View v) {

        if(clickListener!=null){
            clickListener.itemClicked(v, getPosition());
        }

    }
    public static interface PlacesFragmantListener {
        void onLocationSelected(Places places);
    }

    public interface ClickListener{
        public void itemClicked (View view, int position);
    }
}
private class NotifyingDataSetObserver extends DataSetObserver {
    @Override
    public void onChanged() {
        super.onChanged();
        mDataValid = true;
        notifyDataSetChanged();
    }

    @Override
    public void onInvalidated() {
        super.onInvalidated();
        mDataValid = false;
        notifyDataSetChanged();

    }
}
}
你能告诉我我做错了吗

这是日志评论

03-30 04:55:28.042 2318-2318 / com.myapps.pinkas.placesofintrest W / dalvikvm:threadid = 1:线程退出未捕获的异常(group = 0xa4c8cb20) 03-30 04:55:28.042 2318-2318 / com.myapps.pinkas.placesofintrest E / AndroidRuntime:FATAL EXCEPTION:main                                                                                  过程:com.myapps.pinkas.placesofintrest,PID:2318                                                                                  显示java.lang.NullPointerException                                                                                      在com.myapps.pinkas.placesofintrest.PlacesAdapter $ 2.onClick(PlacesAdapter.java:112)                                                                                      在android.view.View.performClick(View.java:4438)                                                                                      在android.view.View $ PerformClick.run(View.java:18422)                                                                                      在android.os.Handler.handleCallback(Handler.java:733)                                                                                      在android.os.Handler.dispatchMessage(Handler.java:95)                                                                                      在android.os.Looper.loop(Looper.java:136)                                                                                      在android.app.ActivityThread.main(ActivityThread.java:5001)                                                                                      at java.lang.reflect.Method.invokeNative(Native Method)                                                                                      在java.lang.reflect.Method.invoke(Method.java:515)                                                                                      在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:785)                                                                                      在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)                                                                                      在dalvik.system.NativeStart.main(本地方法)

2 个答案:

答案 0 :(得分:0)

distance =(TextView)itemView.findViewById(R.id.distanceTextView);

这个行在你的类文件中有112个,看来你没有用XML定义视图id或视图,请查看PlacesAdapter.class中的第112行

答案 1 :(得分:0)

问题1:设置onclick侦听器两次。在onbindviewholder中,您已经将holder.itemView.setOnclicklistener放入静态类视图中,然后再放入itemview.setOnclickListener。当您在静态视图持有者类中指定setOnclicklistener时,这意味着它将以特定的方式表现为不受影响任何其他视图中存在的值(如textview,imageview)或依赖于某些'值的任何此类因素'观点的财产。在大多数情况下,你应该将setOnClicklistener放在静态viewholder类中的itemview / textview / etc中,在你的情况下称为占位符。

问题2:这就是我相信你得到NullPointerException的原因。 onbindviewholder只能访问静态viewholder类中声明的视图。如果您希望onbindviewholder可以访问itemview,请进行以下更改:

public static class PlaceHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

PlacesFragmantListener listener;
View iv;
public PlaceHolder(View itemView, PlacesFragmantListener placesFragmantListener) {
    super(itemView);
    iv = (View)itemView;
    //then rest of the code

现在在你的onbindviewholder中写下以下内容而不是holder.itemview.setonclicklistener

holder.iv.setonclicklistener...

问题3:在静态视图中,你已经放了:

 imgplace.setOnClickListener(this);
 itemView.setOnClickListener(this);

itemview是imgplace存在的布局。而且你们都有setonclicklistener。这就像在按钮上放一个按钮。这没有道理。我想这会让你陷入困境。出于某种原因,您希望两者在单击时执行相同的功能(您已将'this'放在setOnClickListener中)。这完全是不合逻辑的。因此,将clicklistener设置为imgplace或itemview,而不是两者都