2016-04-24 4 views
2

Ich möchte Daten asynchron mit Retrofit2 erhalten, dieser Teil ist gut gemacht, aber mein Adapter für die Recycler-Ansicht wird zuerst eine leere Arraylist als Dataset aber gefüttert Sobald das asynch zurückkommt, werden die Daten dem Adapter hinzugefügt und notifyDAtasetChanged oder notifyRangeinserted wird aufgerufen, abhängig davon, ob die Elementanzahl für den Adapter 0 ist. Meine Frage ist, wie ich das RV in einer solchen Situation richtig aktualisieren soll Ich erhalte immer eine NPE, wenn ich nach einer erfolgreichen Verbindung versuche, die Benutzeroberfläche zu aktualisieren, aber wenn ein Verbindungsfehler auftritt, läuft die App einwandfrei. Wo gehe ich falsch? und btw das ist kein Duplikat von What is a Null Pointer Exception, and how do I fix it? cos Ich frage, wo ich frage, was die richtige Weise ist, eine dynamische, web-abhängige Datenmenge einer Recycler-Ansicht zuzuordnen und nicht, was eine Null-Zeiger-Ausnahme ist. Ich bin eben ein NPE von meiner Bemühungen zu bekommen den DatensatzRichtiger Weg, um heruntergeladene Inhalte zu einem RecyclerView mit Retrofit 2 Asynchrone Anrufe zuzuweisen

hier zuzuordnen ist mein Code: RV Adapter

public class PlaceListRecyclerViewAdapter extends RecyclerView.Adapter<PlaceListRecyclerViewAdapter.PlaceObjectHolder>{ 
private static String LOG_TAG = "PlaceRVAdapter"; 
private ArrayList<Store> mDataSet; 
private static MyClickListener myClickListener; 


public static class PlaceObjectHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 
    protected ImageView placePicture; 
    protected TextView placeName; 

    public PlaceObjectHolder(View view){ 
     super(view); 
     Log.i(LOG_TAG, "Object Holder constructor"); 

     placePicture = (ImageView) view.findViewById(R.id.place_picture); 
     placeName = (TextView) view.findViewById(R.id.place_name); 

     itemView.setOnClickListener(this); 
    } 

    @Override 
    public void onClick(View v) { 
     myClickListener.onItemClick(getAdapterPosition(), v); 
     Log.d(LOG_TAG, "Listener has been called, returning control to calling class"); 
    } 
} 

public void setOnItemClickListener (MyClickListener myClickListener){ 
    PlaceListRecyclerViewAdapter.myClickListener = myClickListener; 
} 

public PlaceListRecyclerViewAdapter(ArrayList<Store> myDataSet){ 
    mDataSet = myDataSet; 
} 

@Override 
public PlaceObjectHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.product_item, parent, false); 
    PlaceObjectHolder productObjectHolder = new PlaceObjectHolder(view); 
    //return new PlaceObjectHolder(view); 
    return productObjectHolder; 
} 


@Override 
public void onBindViewHolder(PlaceObjectHolder holder, int position) { 
    // TODO: Replace with proper, complete logic here 
    if (mDataSet != null) { 
     //FixMe: NPE on this; 
     holder.placeName.setText(mDataSet.get(position).getName()); 
    } 
    // TODO: Image addition goes here 
} 

public void addItems(ArrayList<Store> stores, int index){ 
    int cursize = mDataSet.size(); 
    mDataSet.addAll(index, stores); 
    if (getItemCount() != 0) { 
     notifyItemRangeInserted(index, (mDataSet.size() - cursize)); 
    } else { 
     notifyDataSetChanged(); 
    } 
} 


    public void deleteItem (int index){ 
     mDataSet.remove(index); 
     notifyItemRemoved(index); 
} 

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


    public interface MyClickListener { 
     void onItemClick(int position, View v); 
    } 
} 

Ort Artikel

**<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:cardView="http://schemas.android.com/apk/res-auto" 
android:layout_height="match_parent" 
android:layout_width="match_parent"> 

<android.support.v7.widget.CardView 
android:id="@+id/place_cardview" 
android:layout_height="wrap_content" 
android:layout_width="match_parent" 
android:focusable="true" 
android:layout_gravity="center" 
cardView:cardPreventCornerOverlap="true" 
cardView:cardElevation="15dp"> 

    <ImageView 
     android:id="@+id/place_picture" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" /> 

    <TextView 
     android:id="@+id/place_name" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:padding="10dp" 
     android:textStyle="bold" 
     android:textSize="16dp" /> 
</android.support.v7.widget.CardView> 

</RelativeLayout> 

der anrufende Fragment

PlacesListFragment extends Fragment { 
    private static String LOG_TAG = "PlaceListFragment"; 
    private RecyclerView mRecyclerView; 
    private PlaceListRecyclerViewAdapter mAdapter; 
    private RecyclerView.LayoutManager mLayoutManager; 
    private Context mContext = getContext(); 
    private ArrayList<Store> storePlaces = new ArrayList<Store>(); 
    private ArrayList<Store> viewDataSet = new ArrayList<Store>(); 
    private String BASE_URL; 
    private String FORMAT_SPECIFIER; 
    private TextView storeName; 
    private TextView phoneNumber; 
    private TextView email; 
    private TextView website; 
    private TextView address; 
    private LayoutInflater supinf; 
    int statusCode; 
    int ressize; 
public PlacesListFragment() { 
    // Required empty public constructor 
} 


public static PlacesListFragment newInstance() { 
    PlacesListFragment fragment = new PlacesListFragment(); 
    return fragment; 
} 


@Override 
public void onStart(){ 
    super.onStart(); 

    getDataSet(new com.urbanity.apps.shoplist.adapter.Callback<List<Store>>() { 
        @Override 
        public void next(List<Store> results, int requestCode) { 
         int cursize = mAdapter.getItemCount(); 
         if (statusCode == 200) { 
          viewDataSet.addAll(results); 
          if (cursize != 0) { 
           mAdapter.addItems(viewDataSet, cursize); 
           Log.d(LOG_TAG, "Success, new data set is of size " + storePlaces.size() + " with status code: " + statusCode + " from source sized: " + ressize); 
          } else { 
           mAdapter.addItems(viewDataSet,cursize); 
           mAdapter.notifyDataSetChanged(); 
          } 
         } 
        } 
       }); 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    BASE_URL = getResources().getString(R.string.base_url); 
    FORMAT_SPECIFIER = getResources().getString(R.string.format_specifier); 
    Log.d(LOG_TAG, " Created"); 
} 

@Override 
public void onResume(){ 
    super.onResume(); 
    Log.d(LOG_TAG, " Resumed"); 
    //set listener for this RV adapter instance 
    mAdapter.setOnItemClickListener(new PlaceListRecyclerViewAdapter.MyClickListener() { 
     @Override 
     public void onItemClick(int position, View v) { 
      Log.i(LOG_TAG, " Clicked on Item " + position); 
      Store store = (Store) storePlaces.get(position); 
      // TODO: place ALERT DIALOG here.. 
      displayAlert(supinf); 

     } 
    }); 
} 

public void displayAlert(LayoutInflater inflater){ 
    View selectedPlaceDiag = inflater.inflate(R.layout.dialog_place_details, null); 





    AlertDialog.Builder alert = new AlertDialog.Builder(getContext()); 
    alert.setTitle(R.string.alert_dialog_create_shlist); 
    alert.setView(selectedPlaceDiag); 
    alert.setCancelable(false); 
    alert.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      Toast.makeText(getContext(), R.string.ok, Toast.LENGTH_SHORT).show(); 
     } 
    }); 

    alert.setPositiveButton(R.string.show_map, new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      // TODO: add logic here to display map 
     } 
    }); 
    AlertDialog dialog = alert.create(); 
    dialog.show(); 
} 


public void getDataSet(final com.urbanity.apps.shoplist.adapter.Callback<List<Store>> callback) { 

    Gson gson = new GsonBuilder() 
      .setExclusionStrategies(new ExclusionStrategy() { 
       @Override 
       public boolean shouldSkipField(FieldAttributes f) { 
        return f.getDeclaringClass().equals(RealmObject.class); 
       } 

       @Override 
       public boolean shouldSkipClass(Class<?> clazz) { 
        return false; 
       } 
      }) 
      .create(); 

    Retrofit retrofitClient = new Retrofit.Builder() 
      .baseUrl(BASE_URL) 
      .addConverterFactory(GsonConverterFactory.create(gson)) 
      .build(); 

    // create a new service call variable from the interface with retrofitClient 
    ShoplistApiEndpointInterface apiService = retrofitClient.create(ShoplistApiEndpointInterface.class); 

    //create a new APICall variable of the api interface with its type being that of the call method you'll invoke from the interface 
    Call<List<Store>> storeListCall = apiService.getStoreList(FORMAT_SPECIFIER); 

    // make the call asynchronously by calling enqueue on the Call type 
    //FIXME: chane serverside encoding is option 1 (type:app/json, encoding: utf8) 
    storeListCall.enqueue(new Callback<List<Store>>() { 

     @Override 
     public void onResponse(Call<List<Store>> call, Response<List<Store>> response) { 

      if (response.isSuccessful()) { 
       // get status code from the HTTP response code 
       statusCode = response.code(); 
       // add the parsed response body data (parsed pojo object list in this case) 
       // to the arrayList with the addAll(Collection<type>) method 
       List<Store> results = response.body(); 
       ressize = response.body().size(); 
       //int initialSize = storePlaces.size(); 
       // FIXME: source of NPE? 
       storePlaces.addAll(results);//.addAll(initialSize, results); 

       callback.next(storePlaces, statusCode); 
      } 
     } 

     @Override 
     public void onFailure(Call<List<Store>> call, Throwable t) { 
      // log the error here 
      Log.e(LOG_TAG, "Failed to download Place list", t.getCause()); 
      Toast.makeText(getActivity(), getResources().getString(R.string.failed_to_download_list) + t.getMessage() , Toast.LENGTH_SHORT).show(); 

     } 
    }); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    // Inflate the layout for this fragment 
    View v = inflater.inflate(R.layout.fragment_places_list, container, false); 
    // TODO: in event of an NPE, uncomment this 
    supinf = inflater; 

    Log.d(LOG_TAG, "setting RV"); 
    mRecyclerView = (RecyclerView) v.findViewById(R.id.place_list_rv); 
    mRecyclerView.setHasFixedSize(true); 
    mLayoutManager = new GridLayoutManager(mContext, 2, GridLayoutManager.VERTICAL, false); 
    Log.d(LOG_TAG, "setting Layout Manager"); 
    mRecyclerView.setLayoutManager(mLayoutManager); 
    Log.d(LOG_TAG, "setting dataset"); 
    mAdapter = new PlaceListRecyclerViewAdapter(storePlaces); 
    Log.d(LOG_TAG, "setting adapter"); 
    mRecyclerView.setAdapter(mAdapter); 

    Log.d(LOG_TAG, "Setting up endless scrolling listener"); 
    mRecyclerView.addOnScrollListener(new EndlessRecyclerViewScrollListener((GridLayoutManager) mLayoutManager) { 
     @Override 
     public void onLoadMore(int page, int totalItemsCount) { 
      //Query server for more data 
      getDataSet(new com.urbanity.apps.shoplist.adapter.Callback<List<Store>>() { 
       @Override 
       public void next(List<Store> result, int requestCode) { 
        ArrayList<Store> stores = new ArrayList<Store>(); 
        stores.addAll(result); 
        int cursize = mAdapter.getItemCount(); 
        mAdapter.addItems(stores, cursize); 
       } 
      }); 
     } 
    }); 
    Log.d(LOG_TAG, " returning view"); 

    AppCompatButton showMap = (AppCompatButton) v.findViewById(R.id.btn_show_map); 

    showMap.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      showOnMap(); 
     } 
    }); 

    getActivity().setTitle(R.string.store_locator); 

    return v; 
} 

public void showOnMap(){ 
    // Insert the fragment by replacing any existing fragment 
    SupportMapFragment mapFragment = PlacesListMapFragment.newInstance(); 
    FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction(); 
    fragmentTransaction.replace(R.id.flContent, mapFragment); 
    fragmentTransaction.addToBackStack(null); 
    fragmentTransaction.commit(); 
} 

und schließlich beginnt das Protokoll ab dem Punkt Hauptaktivität t er fragmentieren Transaktion

04-21 16:33:57.690 17420-17420/com.urbanity.apps.shoplist D/MainActivity:: : fragment replaced with FragmentClass data 
    04-21 16:33:57.710 17420-17420/com.urbanity.apps.shoplist D/PlaceListFragment: Created 
    04-21 16:33:57.720 17420-17420/com.urbanity.apps.shoplist D/PlaceListFragment: setting RV 
    04-21 16:33:57.720 17420-17420/com.urbanity.apps.shoplist D/PlaceListFragment: setting Layout Manager 
    04-21 16:33:57.720 17420-17420/com.urbanity.apps.shoplist D/PlaceListFragment: setting dataset 
    04-21 16:33:57.720 17420-17420/com.urbanity.apps.shoplist D/PlaceListFragment: setting adapter 
    04-21 16:33:57.720 17420-17420/com.urbanity.apps.shoplist D/PlaceListFragment: Setting up endless scrolling listener 
    04-21 16:33:57.720 17420-17420/com.urbanity.apps.shoplist D/PlaceListFragment: returning view 
    04-21 16:33:57.790 17420-17420/com.urbanity.apps.shoplist D/PlaceListFragment: Resumed 
    04-21 16:33:59.740 17420-17502/com.urbanity.apps.shoplist W/dalvikvm: VFY: unable to find class referenced in signature (Ljava/nio/file/Path;) 
    04-21 16:33:59.740 17420-17502/com.urbanity.apps.shoplist W/dalvikvm: VFY: unable to find class referenced in signature ([Ljava/nio/file/OpenOption;) 
    04-21 16:33:59.740 17420-17502/com.urbanity.apps.shoplist I/dalvikvm: Could not find method java.nio.file.Files.newOutputStream, referenced from method okio.Okio.sink 
    04-21 16:33:59.740 17420-17502/com.urbanity.apps.shoplist W/dalvikvm: VFY: unable to resolve static method 61886: Ljava/nio/file/Files;.newOutputStream (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/io/OutputStream; 
    04-21 16:33:59.740 17420-17502/com.urbanity.apps.shoplist D/dalvikvm: VFY: replacing opcode 0x71 at 0x000a 
    04-21 16:33:59.740 17420-17502/com.urbanity.apps.shoplist W/dalvikvm: VFY: unable to find class referenced in signature (Ljava/nio/file/Path;) 
    04-21 16:33:59.740 17420-17502/com.urbanity.apps.shoplist W/dalvikvm: VFY: unable to find class referenced in signature ([Ljava/nio/file/OpenOption;) 
    04-21 16:33:59.750 17420-17502/com.urbanity.apps.shoplist I/dalvikvm: Could not find method java.nio.file.Files.newInputStream, referenced from method okio.Okio.source 
    04-21 16:33:59.750 17420-17502/com.urbanity.apps.shoplist W/dalvikvm: VFY: unable to resolve static method 61885: Ljava/nio/file/Files;.newInputStream (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/io/InputStream; 
    04-21 16:33:59.750 17420-17502/com.urbanity.apps.shoplist D/dalvikvm: VFY: replacing opcode 0x71 at 0x000a 
    04-21 16:34:01.140 17420-17420/com.urbanity.apps.shoplist D/PlaceListFragment: Success, new data set is of size 4 with status code: 200 from source sized: 2 
    04-21 16:34:01.170 17420-17420/com.urbanity.apps.shoplist I/PlaceRVAdapter: Object Holder constructor 
    04-21 16:34:01.170 17420-17420/com.urbanity.apps.shoplist D/AndroidRuntime: Shutting down VM 
    04-21 16:34:01.170 17420-17420/com.urbanity.apps.shoplist W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x4162ae00) 
    04-21 16:34:01.210 17420-17420/com.urbanity.apps.shoplist E/AndroidRuntime: FATAL EXCEPTION: main 
                       Process: com.urbanity.apps.shoplist, PID: 17420 
                       java.lang.NullPointerException 
                        at com.urbanity.apps.shoplist.adapter.PlaceListRecyclerViewAdapter.onBindViewHolder(PlaceListRecyclerViewAdapter.java:69) 
                        at com.urbanity.apps.shoplist.adapter.PlaceListRecyclerViewAdapter.onBindViewHolder(PlaceListRecyclerViewAdapter.java:20) 
                        at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5453) 
                        at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5486) 
                        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4723) 
                        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4599) 
                        at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1988) 
                        at android.support.v7.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:528) 
                        at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1347) 
                        at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:574) 
                        at android.support.v7.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170) 
                        at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3003) 
                        at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2881) 
                        at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1457) 
                        at android.support.v7.widget.RecyclerView.access$400(RecyclerView.java:147) 
                        at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:285) 
                        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:768) 
                        at android.view.Choreographer.doCallbacks(Choreographer.java:581) 
                        at android.view.Choreographer.doFrame(Choreographer.java:550) 
                        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:754) 
                        at android.os.Handler.handleCallback(Handler.java:733) 
                        at android.os.Handler.dispatchMessage(Handler.java:95) 
                        at android.os.Looper.loop(Looper.java:136) 
                        at android.app.ActivityThread.main(ActivityThread.java:5333) 
                        at java.lang.reflect.Method.invokeNative(Native Method) 
                        at java.lang.reflect.Method.invoke(Method.java:515) 
                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:895) 
                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:711) 
                        at dalvik.system.NativeStart.main(Native Method) 
    04-21 16:39:01.380 17420-17420/com.urbanity.apps.shoplist I/Process: Sending signal. PID: 17420 SIG: 9 
    04-21 16:44:52.530 22302-22320/com.urbanity.apps.shoplist I/GMPM: Tag Manager is not found and thus will not be used 

Antwort

0

fand ich, was ich wron habe .. weiß nicht, was es war genau das, aber m Adapter war die Ursache für die NPE, so klebte ich eine Kopie von einem anderen meiner Adapter Anzeige geändert, was gebraucht geändert werden. Dies ist der Arbeitsadapter:

public class PlaceListRecyclerViewAdapter extends RecyclerView.Adapter<PlaceListRecyclerViewAdapter.StoreObjectHolder>{ 
    private static String LOG_TAG = "StoreRecyclerViewAdapter: "; 
    private ArrayList <Store> mDataSet; 
    private static MyClickListener myClickListener; 



    public static class StoreObjectHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 
     protected ImageView StoreImage; 
     protected TextView StoreName; 
     protected TextView StorePrice; 
     public StoreObjectHolder(View view){ 
      super(view); 
      StoreImage = (ImageView) view.findViewById(R.id.place_picture); 
      StoreName = (TextView) view.findViewById(R.id.place_name); 
      Log.i(LOG_TAG, "Adding Listener"); 
      itemView.setOnClickListener(this); 
     } 

     @Override 
     public void onClick(View v) { 
      myClickListener.onItemClick(getAdapterPosition(), v); 
      Log.d(LOG_TAG, "Listener has been called, returning control to calling class"); 
     } 
    } 

    public void setOnItemClickListener (MyClickListener myClickListener){ 
     PlaceListRecyclerViewAdapter.myClickListener = myClickListener; 
    } 

    public PlaceListRecyclerViewAdapter(ArrayList<Store> myDataSet){ 
     mDataSet = myDataSet; 
    } 

    @Override 
    public StoreObjectHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.place_item, parent, false); 
     StoreObjectHolder StoreObjectHolder = new StoreObjectHolder(view); 
     //return new StoreObjectHolder(view); 
     return StoreObjectHolder; 
    } 

    @Override 
    public void onBindViewHolder(StoreObjectHolder holder, int position) { 
     // TODO: Replace with proper, complete logic here 
     holder.StoreName.setText(mDataSet.get(position).getName()); 
    } 

    public void addItems(ArrayList<Store> stores, int index){ 
     int cursize = mDataSet.size(); 
     mDataSet.addAll(index, stores); 
     if (getItemCount() != 0) { 
      notifyItemRangeInserted(index, (mDataSet.size() - cursize)); 
     } else { 
      notifyDataSetChanged(); 
     } 
    } 

    public void deleteItem (int index){ 
     mDataSet.remove(index); 
     notifyItemRemoved(index); 
    } 

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

    public interface MyClickListener { 
     void onItemClick(int position, View v); 
    } 
} 
Verwandte Themen