2016-04-24 5 views
2

Retrofit2と非同期的にデータを取得したいが、その部分はうまくいっているが、リサイクラビューのアダプタにはデータセットとして空のarraylist asynchが返すとすぐにデータがアダプタに追加され、アダプタの項目数が0かどうかによってnotifyDAtasetChangedまたはnotifyRangeinsertedが呼び出されます。私の質問はどうやってこのような状況でRVを正しく更新するのでしょうか?正常に接続した後にUIを更新しようとするとNPEを取得し続けるが、接続エラーが発生した場合はアプリが正しく動作する。どこが間違っていますか? btwこれはWhat is a Null Pointer Exception, and how do I fix it?の複製ではありません。なぜなら、リサイクラビューに動的なウェブ依存データセットを割り当てる適切な方法と、nullポインタ例外とは何なのかを尋ねているところです。私は、データセットここRetrofit 2でダウンロードしたコンテンツを適切に割り当てる方法非同期呼び出し

を割り当てるには、私の努力からNPEを取得することが起こることは私のコードです: RVアダプタ

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); 
    } 
} 

場所項目

**<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> 

呼び出しフラグメント

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(); 
} 

最後に、メインアクティビティのポイントから開始するログは、彼は取引

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 

答えて

0

を断片化私はwron ..いけない、それは正確に何であったかを知っていたが、m個のアダプタはNPEの原因だったので、私は広告が必要なものを変え、私のアダプタのもう一つのコピーを貼り付けたものを見つけ変更する。これは動作中のアダプタです:

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); 
    } 
} 
関連する問題