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