Android Paging library Index out of bound exception - java

i am implementing paging library in android all works fine if item of all pages are the same. When item of last page items size is 1 rather then 10 it gives a exception. i am using paging library 2.1.1 with androidx.
Exception
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dasfilm.azzeddine.dasfilm, PID: 22472
java.lang.IndexOutOfBoundsException: Index: 4, Size: 4
at java.util.ArrayList.get(ArrayList.java:437)
at androidx.paging.PagedStorage.get(PagedStorage.java:152)
at androidx.paging.PagedList.get(PagedList.java:384)
at androidx.paging.AsyncPagedListDiffer.getItem(AsyncPagedListDiffer.java:206)
at androidx.paging.PagedListAdapter.getItem(PagedListAdapter.java:156)
at com.dasfilm.azzeddine.dasfilm.Views.Adapters.FreshoneProductPaggingAdapter.onBindViewHolder(FreshoneProductPaggingAdapter.java:56)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:286)
at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:343)
at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:359)
at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:366)
at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:397)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
DataSource Class : This is my data source class with is getting data from web service
public class MoviesInTheaterDataSource extends PageKeyedDataSource<Integer, FreshProduct> {
private static final String TAG = "MoviesInTheaterDataSou";
private ProductApiCall tmdbWebService;
private MutableLiveData<NetworkState> networkState;
private MutableLiveData<NetworkState> initialLoading;
private Executor retryExecutor;
public MoviesInTheaterDataSource(Executor retryExecutor,ProductApiCall webService) {
tmdbWebService = webService;
networkState = new MutableLiveData<>();
initialLoading = new MutableLiveData<>();
this.retryExecutor = retryExecutor;
}
public MutableLiveData<NetworkState> getNetworkState() {
return networkState;
}
public MutableLiveData getInitialLoading() {
return initialLoading;
}
#Override
public void loadInitial(#NonNull final LoadInitialParams<Integer> params, #NonNull final LoadInitialCallback<Integer, FreshProduct> callback) {
Log.d(TAG, "loadInitial: ");
initialLoading.postValue(NetworkState.LOADING);
networkState.postValue(NetworkState.LOADING);
tmdbWebService.getProductList(1,"","",1);
tmdbWebService.SetListenersProduct(new ProductApiCall.ListenersProduct() {
#Override
public void onSuccess(List<FreshProduct> itemList, int totalPageCount) {
initialLoading.postValue(NetworkState.LOADING);
int loadsize = params.requestedLoadSize;
callback.onResult(itemList, 1, 2);
networkState.postValue(NetworkState.LOADED);
}
});
}
#Override
public void loadBefore(#NonNull LoadParams<Integer> params, #NonNull LoadCallback<Integer, FreshProduct> callback) {
}
#Override
public void loadAfter(#NonNull final LoadParams<Integer> params, #NonNull final LoadCallback<Integer, FreshProduct> callback) {
networkState.postValue(NetworkState.LOADING);
tmdbWebService.getProductList(1,"","",params.key);
tmdbWebService.SetListenersProduct(new ProductApiCall.ListenersProduct() {
#Override
public void onSuccess(List<FreshProduct> itemList, int totalPageCount) {
initialLoading.postValue(NetworkState.LOADING);
networkState.postValue(NetworkState.LOADED);
callback.onResult(itemList, params.key+1);
networkState.postValue(NetworkState.LOADED);
}
});
}
}
DataSource Factory Class
public class MoviesInTheaterDataSource extends PageKeyedDataSource<Integer, FreshProduct> {
private static final String TAG = "MoviesInTheaterDataSou";
private ProductApiCall tmdbWebService;
private MutableLiveData<NetworkState> networkState;
private MutableLiveData<NetworkState> initialLoading;
private Executor retryExecutor;
public MoviesInTheaterDataSource(Executor retryExecutor,ProductApiCall webService) {
tmdbWebService = webService;
networkState = new MutableLiveData<>();
initialLoading = new MutableLiveData<>();
this.retryExecutor = retryExecutor;
}
public MutableLiveData<NetworkState> getNetworkState() {
return networkState;
}
public MutableLiveData getInitialLoading() {
return initialLoading;
}
#Override
public void loadInitial(#NonNull final LoadInitialParams<Integer> params, #NonNull final LoadInitialCallback<Integer, FreshProduct> callback) {
Log.d(TAG, "loadInitial: ");
initialLoading.postValue(NetworkState.LOADING);
networkState.postValue(NetworkState.LOADING);
tmdbWebService.getProductList(1,"","",1);
tmdbWebService.SetListenersProduct(new ProductApiCall.ListenersProduct() {
#Override
public void onSuccess(List<FreshProduct> itemList, int totalPageCount) {
initialLoading.postValue(NetworkState.LOADING);
int loadsize = params.requestedLoadSize;
callback.onResult(itemList, 1, 2);
networkState.postValue(NetworkState.LOADED);
}
});
}
#Override
public void loadBefore(#NonNull LoadParams<Integer> params, #NonNull LoadCallback<Integer, FreshProduct> callback) {
}
#Override
public void loadAfter(#NonNull final LoadParams<Integer> params, #NonNull final LoadCallback<Integer, FreshProduct> callback) {
networkState.postValue(NetworkState.LOADING);
tmdbWebService.getProductList(1,"","",params.key);
tmdbWebService.SetListenersProduct(new ProductApiCall.ListenersProduct() {
#Override
public void onSuccess(List<FreshProduct> itemList, int totalPageCount) {
initialLoading.postValue(NetworkState.LOADING);
networkState.postValue(NetworkState.LOADED);
callback.onResult(itemList, params.key+1);
networkState.postValue(NetworkState.LOADED);
}
});
}
}
ViewModel Class
public class MoviesInTheaterViewModel extends ViewModel {
private static final String TAG = "TheaterViewModel";
private LiveData<PagedList<FreshProduct>> moviesInTheaterList;
private LiveData<NetworkState> networkStateLiveData;
private Executor executor;
private LiveData<MoviesInTheaterDataSource> dataSource;
public MoviesInTheaterViewModel() {
Log.d(TAG, "MoviesInTheaterViewModel: ");
executor = Executors.newFixedThreadPool(5);
ProductApiCall webService = new ProductApiCall(MyApp.getInstance().getApplicationContext());
MoviesInTheaterDataSourceFactory factory = new MoviesInTheaterDataSourceFactory(executor,webService);
dataSource = factory.getMutableLiveData();
networkStateLiveData = Transformations.switchMap(factory.getMutableLiveData(), new Function<MoviesInTheaterDataSource, LiveData<NetworkState>>() {
#Override
public LiveData<NetworkState> apply(MoviesInTheaterDataSource source) {
Log.d(TAG, "apply: network change");
return source.getNetworkState();
}
});
PagedList.Config pageConfig = (new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setPageSize(10)
.build();
moviesInTheaterList = (new LivePagedListBuilder<Integer,FreshProduct>(factory,pageConfig))
.setFetchExecutor(executor)
.build();
}
public LiveData<PagedList<FreshProduct>> getMoviesInTheaterList() {
Log.d(TAG, "getMoviesInTheaterList: ");
return moviesInTheaterList;
}
public LiveData<NetworkState> getNetworkStateLiveData() {
return networkStateLiveData;
}
}
Activity Class
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private MoviesInTheaterViewModel mMoviesViewModel;
private RecyclerView mRecyclerView;
private FreshoneProductPaggingAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: ");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.list);
adapter = new FreshoneProductPaggingAdapter(this);
mMoviesViewModel = ViewModelProviders.of(this).get(MoviesInTheaterViewModel.class);
mMoviesViewModel.getMoviesInTheaterList().observe(this, new Observer<PagedList<FreshProduct>>() {
#Override
public void onChanged(#Nullable PagedList<FreshProduct> movies) {
Log.d(TAG, "onChanged: "+movies.size());
adapter.submitList(movies);
}
});
mMoviesViewModel.getNetworkStateLiveData().observe(this, new Observer<NetworkState>() {
#Override
public void onChanged(#Nullable NetworkState networkState) {
Log.d(TAG, "onChanged: network state changed");
adapter.setNetworkState(networkState);
}
});
mRecyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false));
mRecyclerView.setAdapter(adapter);
}
}

Paging2 doesn't support variable page sizes, you need to migrate to Paging3 (still in alpha) for that functionality. This is partially due to how tiling support was implemented, but Paging3 has rewritten things from the ground up to remove this constraint.

Related

Why #update generates so many returns despite removeObservers

Can someone explain my error by showing me why each update of the Room database causes an event on the liveData despite the removeObservers that I apply before?
When I reactivate observe, I have as many events as there were updates. If I do 6 updateLobjet, I can have updateLobjetsList 8 times.
What should I do to be notified only once, or none if one is not possible, but continuing to observe for next event?
I need to use a LiveData to retrieve my data from the Room database and have it displayed by the RecyclerView.
I really need help to solve that.
Fragment:
public class MainFragment extends Fragment {
private ArrayList<Lobjet> mLobjets = new ArrayList<>();
RecyclerView mRecyclerView;
private LobjetViewModel mLobjetViewModel;
SampleAdapter mSampleAdapter;
LiveData<List<Lobjet>> mLDgetAll;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
this.mSampleAdapter = new SampleAdapter();
this.mRecyclerView = view.findViewById(R.id.sampleRecyclerView);
this.mRecyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
this.mRecyclerView.setAdapter(this.mSampleAdapter);
Button add = view.findViewById(R.id.add);
add.setOnClickListener(v -> {
Random r = new Random();
this.mLobjetViewModel.insertLobjet(new Lobjet("Lobjet" + (r.nextInt(9999)), this.mLobjets.size()));
});
this.mLobjetViewModel = new ViewModelProvider(this, ViewModelFactory.getInstance(getContext())).get(LobjetViewModel.class);
this.mLDgetAll = this.mLobjetViewModel.getAll();
this.mLDgetAll.observe(getViewLifecycleOwner(), this::updateLobjetsList);
this.setUpItemTouchHelper();
return view;
}
public void updateLobjetsList(List<Lobjet> lobjets) {
this.mSampleAdapter.setAdapterDatas(this.mLobjets = new ArrayList<>(lobjets));
}
private void updateLobjet(Lobjet lobjet) {
this.mLobjetViewModel.updateLobjet(lobjet);
}
private void setUpItemTouchHelper() {
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0) {
#Override
public int getSwipeDirs(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder) {
// pas de swipe en mode sélection d'articles
return super.getSwipeDirs(recyclerView, viewHolder);
}
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
final int from = viewHolder.getBindingAdapterPosition();
final int to = target.getBindingAdapterPosition();
Collections.swap(mLobjets, from, to);
mSampleAdapter.notifyItemMoved(from, to);
return true;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
// mettre à jour les données à la fin du drop
#Override
public void clearView(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if (mLDgetAll != null && mLDgetAll.hasObservers())
mLDgetAll.removeObservers(getViewLifecycleOwner());
for (int i = 0; i < mLobjets.size(); i++) {
mLobjets.get(i).setOrder(i);
updateLobjet(mLobjets.get(i));
}
if (mLDgetAll != null) {
mLDgetAll.observe(getViewLifecycleOwner(),
lobjets -> {
updateLobjetsList(lobjets);
});
}
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(this.mRecyclerView);
}
}
Model:
#Entity(indices = {
#Index(value = {"id"}, unique = true),
#Index(value = {"lobjetName"}, unique = true)
})
public class Lobjet {
#PrimaryKey(autoGenerate = true)
private long id;
#ColumnInfo(name = "lobjetName")
private String name;
private long order;
public Lobjet(String name, long order) {
this.name = name;
this.order = order;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
public void setId(long id) {
this.id = id;
}
public long getOrder() {
return order;
}
public void setOrder(long order) {
this.order = order;
}
}
Dao:
#Dao
public interface LobjetDao {
#Insert(onConflict = OnConflictStrategy.REPLACE)
long createLobjet(Lobjet lobjet);
#Query("SELECT * FROM Lobjet ORDER BY `order`, lobjetName")
LiveData<List<Lobjet>> getAll();
#Update
int updateLobjet(Lobjet lobjet);
}
Database:
#Database(
version = 1,
entities = {Lobjet.class},
)
public abstract class getDB extends RoomDatabase {
private static final String DB_NAME = "MyDatabase.db";
private static getDB INSTANCE;
public static synchronized getDB getInstance(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), getDB.class, DB_NAME)
.fallbackToDestructiveMigration()
.build();
}
return INSTANCE;
}
public abstract LobjetDao lobjetDao();
}
Factory:
public class ViewModelFactory implements ViewModelProvider.Factory {
private final LobjetDataRepository lobjetDataSource;
private final Executor executor;
private static volatile ViewModelFactory factory;
public static ViewModelFactory getInstance(Context context) {
if (factory == null) {
synchronized (ViewModelFactory.class) {
if (factory == null) {
factory = new ViewModelFactory(context);
}
}
}
return factory;
}
private ViewModelFactory(Context context) {
getDB database = getDB.getInstance(context);
this.lobjetDataSource = new LobjetDataRepository(database.lobjetDao());
this.executor = Executors.newSingleThreadExecutor();
}
#Override
#NotNull
public <T extends ViewModel> T create(Class<T> modelClass) {
if (modelClass.isAssignableFrom(LobjetViewModel.class)) {
return (T) new LobjetViewModel(lobjetDataSource, executor);
}
throw new IllegalArgumentException("Unknown ViewModel class");
}
}
Repository:
public class LobjetDataRepository {
private final LobjetDao mLobjetDao;
public LobjetDataRepository(LobjetDao lobjetDao) {
this.mLobjetDao = lobjetDao;
}
public LiveData<List<Lobjet>> getAll() {
return this.mLobjetDao.getAll();
}
public void createLobjet(Lobjet lobjet) {
lobjet.setId(mLobjetDao.createLobjet(lobjet));
}
public void updateLobjet(Lobjet lobjet) {
mLobjetDao.updateLobjet(lobjet);
}
}
ViewModel:
public class LobjetViewModel extends ViewModel {
private final LobjetDataRepository lobjetDataSource;
private final Executor executor;
public LobjetViewModel(LobjetDataRepository lobjetDataSource, Executor executor) {
this.lobjetDataSource = lobjetDataSource;
this.executor = executor;
}
public LiveData<List<Lobjet>> getAll() {
return lobjetDataSource.getAll();
}
public void insertLobjet(Lobjet lobjet) {
executor.execute(() -> lobjetDataSource.createLobjet(lobjet));
}
public void updateLobjet(Lobjet lobjet) {
executor.execute(() -> lobjetDataSource.updateLobjet(lobjet));
}
}

Android PagedList not showing data from local if offline?

I have done various ways, but to no avail
DataSource
public class NetReqDataSourceFactory extends DataSource.Factory {
private static final String TAG = NetReqDataSourceFactory.class.getSimpleName();
private MutableLiveData<NetReqPageKeyedDataSource> networkStatus;
private NetReqPageKeyedDataSource moviesPageKeyedDataSource;
public NetReqDataSourceFactory(Context context, String status) {
this.networkStatus = new MutableLiveData<>();
moviesPageKeyedDataSource = new NetReqPageKeyedDataSource(context, status);
}
#Override
public DataSource create() {
networkStatus.postValue(moviesPageKeyedDataSource);
return moviesPageKeyedDataSource;
}
public MutableLiveData<NetReqPageKeyedDataSource> getNetworkStatus() {
return networkStatus;
}
public ReplaySubject<ReqDataList> getData() {
return moviesPageKeyedDataSource.getData();
}
}
PageKeyedDataSource
public class NetReqPageKeyedDataSource extends PageKeyedDataSource<String, ReqDataList> {
private static final String TAG = NetReqPageKeyedDataSource.class.getSimpleName();
private final MutableLiveData networkState;
private final ReplaySubject<ReqDataList> moviesObservable;
private final ConnectionServer connectionServer;
private final String status;
private final MasterRepository repository;
NetReqPageKeyedDataSource(Context context, String status) {
networkState = new MutableLiveData();
connectionServer = new ConnectionServer(Util.getApiWithAuth(context, (new ArrayList<ReqDataList>()).getClass(), new ReqJsonDeserializer()));
moviesObservable = ReplaySubject.create();
this.status = status;
this.repository = MasterRepository.getInstance(context);
}
public MutableLiveData getNetworkState() {
return networkState;
}
public ReplaySubject<ReqDataList> getData() {
return moviesObservable;
}
#Override
public void loadInitial(#NonNull LoadInitialParams<String> params, #NonNull final LoadInitialCallback<String, ReqDataList> callback) {
Log.i(TAG, "Loading Initial Rang, Count " + params.requestedLoadSize);
Log.i(TAG, "Loading Initial, Status " + status);
networkState.postValue(NetworkState.FIRST_LOADING);
connectionServer.getReqByPage(1, status).enqueue(new Callback<ArrayList<ReqDataList>>() {
#Override
public void onResponse(Call<ArrayList<ReqDataList>> call, Response<ArrayList<ReqDataList>> response) {
if (response.isSuccessful()) {
callback.onResult(response.body(), Integer.toString(1), Integer.toString(2));
networkState.postValue(NetworkState.LOADED);
if (response.body().size() > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
response.body().forEach(moviesObservable::onNext);
} else {
for (ReqDataList data : response.body()) {
moviesObservable.onNext(data);
}
}
} else {
networkState.postValue(new NetworkState(NetworkState.Status.FIRST_FAILED, "Nothing here yet, pull to refresh & try again"));
}
} else {
Log.e("API CALL", response.message());
networkState.postValue(new NetworkState(NetworkState.Status.FIRST_FAILED, response.message()));
}
}
#Override
public void onFailure(Call<ArrayList<ReqDataList>> call, Throwable t) {
String errorMessage;
if (t.getMessage() == null) {
errorMessage = "unknown error";
} else {
errorMessage = t.getMessage();
}
networkState.postValue(new NetworkState(NetworkState.Status.FIRST_FAILED, errorMessage));
callback.onResult(new ArrayList<>(), Integer.toString(1), Integer.toString(2));
}
});
}
#Override
public void loadAfter(#NonNull LoadParams<String> params, final #NonNull LoadCallback<String, ReqDataList> callback) {
Log.i(TAG, "Loading page " + params.key );
networkState.postValue(NetworkState.LOADING);
final AtomicInteger page = new AtomicInteger(0);
try {
page.set(Integer.parseInt(params.key));
}catch (NumberFormatException e){
e.printStackTrace();
}
Call<ArrayList<ReqDataList>> callBack = connectionServer.getReqByPage(page.get(), status);
callBack.enqueue(new Callback<ArrayList<ReqDataList>>() {
#Override
public void onResponse(Call<ArrayList<ReqDataList>> call, Response<ArrayList<ReqDataList>> response) {
if (response.isSuccessful()) {
callback.onResult(response.body(), Integer.toString(page.get() + 1));
networkState.postValue(NetworkState.LOADED);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
response.body().forEach(moviesObservable::onNext);
} else {
for (ReqDataList data : response.body()) {
moviesObservable.onNext(data);
}
}
} else {
networkState.postValue(new NetworkState(NetworkState.Status.FAILED, response.message()));
Log.e("API CALL", response.message());
}
}
#Override
public void onFailure(Call<ArrayList<ReqDataList>> call, Throwable t) {
String errorMessage;
if (t.getMessage() == null) {
errorMessage = "unknown error";
} else {
errorMessage = t.getMessage();
}
networkState.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage));
callback.onResult(new ArrayList<>(), Integer.toString(page.get()));
}
});
}
#Override
public void loadBefore(#NonNull LoadParams<String> params, #NonNull LoadCallback<String, ReqDataList> callback) {
}
}
PagedList.Config
public class ReqNetwork {
final private static String TAG = ReqNetwork.class.getSimpleName();
final private LiveData<PagedList<ReqDataList>> moviesPaged;
final private LiveData<NetworkState> networkState;
public ReqNetwork(NetReqDataSourceFactory dataSourceFactory, PagedList.BoundaryCallback<ReqDataList> boundaryCallback) {
PagedList.Config pagedListConfig = (new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setInitialLoadSizeHint(20)
.setPageSize(10)
.build();
networkState = Transformations.switchMap(
dataSourceFactory.getNetworkStatus(),
(Function<NetReqPageKeyedDataSource, LiveData<NetworkState>>) NetReqPageKeyedDataSource::getNetworkState
);
Executor executor = Executors.newFixedThreadPool(3);
LivePagedListBuilder livePagedListBuilder = new LivePagedListBuilder(dataSourceFactory, pagedListConfig);
moviesPaged = livePagedListBuilder.
setFetchExecutor(executor).
setBoundaryCallback(boundaryCallback).
build();
}
public LiveData<PagedList<ReqDataList>> getPagedMovies() {
return moviesPaged;
}
public LiveData<NetworkState> getNetworkState() {
return networkState;
}
}
LocalDataSource
public class DbReqDataSourceFactory extends DataSource.Factory {
private static final String TAG = DbReqDataSourceFactory.class.getSimpleName();
private DbReqPageKeyedDataSource moviesPageKeyedDataSource;
public DbReqDataSourceFactory(ReqDataDao dao, String filterStatus) {
moviesPageKeyedDataSource = new DbReqPageKeyedDataSource(dao, filterStatus);
}
#Override
public DataSource create() {
return moviesPageKeyedDataSource;
}
}
LocalPageKeyedDataSource
public class DbReqPageKeyedDataSource extends PageKeyedDataSource<String, ReqDataList> {
public static final String TAG = DbReqPageKeyedDataSource.class.getSimpleName();
private final ReqDataDao dataDao;
private String filterStatus;
public DbReqPageKeyedDataSource(ReqDataDao dao, String status) {
dataDao = dao;
filterStatus = status;
}
#Override
public void loadInitial(#NonNull LoadInitialParams<String> params, #NonNull final LoadInitialCallback<String, ReqDataList> callback) {
Log.i(TAG, "Loading Initial Rang, Count " + params.requestedLoadSize);
Log.w(TAG, "loadInitial: " + filterStatus);
List<ReqDataList> data = null;
if (filterStatus == null) {
data = dataDao.getListAll();
} else {
data = dataDao.getListAllByStatus(filterStatus);
}
if(data.size() != 0) {
callback.onResult(data, "0", "1");
}
}
#Override
public void loadAfter(#NonNull LoadParams<String> params, final #NonNull LoadCallback<String, ReqDataList> callback) {
}
#Override
public void loadBefore(#NonNull LoadParams<String> params, #NonNull LoadCallback<String, ReqDataList> callback) {
}
}
Repository
public LiveData<PagedList<ReqDataList>> getDataReqPage(Context context, String status){
initReqPageDao(status);
NetReqDataSourceFactory dataSourceFactory = new NetReqDataSourceFactory(context, status);
network = new ReqNetwork(dataSourceFactory, reqBoundaryCallback);
reqLiveDataMerger = new MediatorLiveData<>();
reqLiveDataMerger.addSource(network.getPagedMovies(), value -> {
reqLiveDataMerger.setValue(value);
Log.d(TAG, value.toString());
});
dataSourceFactory.getData().
observeOn(Schedulers.io()).
subscribe(item -> {
ReqData reqData = new ReqData();
reqData.req_sid = item.req_sid;
reqData.req_uid = item.req_uid;
reqData.req_total = item.req_total;
reqData.req_pemda = item.req_pemda;
reqData.req_lon = item.req_lon;
reqData.req_lat = item.req_lat;
reqData.req_address = item.req_address;
reqData.req_remark = item.req_remark;
reqData.address_id = item.address_id;
reqData.post_by = item.post_by;
reqData.post_date = item.post_date;
reqData.update_by = item.update_by;
reqData.update_date = item.update_date;
reqData.post_status = 1;
database.dataReqDao().insert(reqData);
});
return reqLiveDataMerger;
}
public void initReqPageDao(String status) {
PagedList.Config pagedListConfig = (new PagedList.Config.Builder()).setEnablePlaceholders(false)
.setInitialLoadSizeHint(Integer.MAX_VALUE).setPageSize(Integer.MAX_VALUE).build();
Executor executor = Executors.newFixedThreadPool(3);
DbReqDataSourceFactory dataSourceFactory = new DbReqDataSourceFactory(database.dataReqDao(), status);
LivePagedListBuilder livePagedListBuilder = new LivePagedListBuilder(dataSourceFactory, pagedListConfig);
reqPaged = livePagedListBuilder.setFetchExecutor(executor).build();
}
private PagedList.BoundaryCallback<ReqDataList> reqBoundaryCallback = new PagedList.BoundaryCallback<ReqDataList>() {
#Override
public void onZeroItemsLoaded() {
super.onZeroItemsLoaded();
reqLiveDataMerger.addSource(getReqData(), value -> {
reqLiveDataMerger.setValue(value);
reqLiveDataMerger.removeSource(getReqData());
});
}
};
public LiveData<PagedList<ReqDataList>> getReqData() {
return reqPaged;
}
ViewModel
public LiveData<PagedList<ReqDataList>> getReqDataPaged(String status) {
return getRepository().getDataReqPage(getContext(), status);
}
public LiveData<NetworkState> getNetworkState() {
return getRepository().getNetworkState();
}
Did you guys find my fault?
I load data using a Fragment inside the ViewPager
public class ReqListFragment extends BaseFragment<FragmentReqListBinding, ReqListViewModel> implements ReqListViewModel.Navigator {
#Inject
ConnectionServer server;
#Inject
MasterRepository repository;
private FragmentReqListBinding binding;
private ReqListViewModel viewModel;
private String status;
private boolean hasLoaded = false;
#Override
public int getBindingVariable() {
return 0;
}
#Override
public int getLayoutId() {
return R.layout.fragment_req_list;
}
#Override
public ReqListViewModel getViewModel() {
return viewModel;
}
public ReqListFragment newInstance(String status) {
ReqListFragment fragment = new ReqListFragment();
Bundle bundle = new Bundle();
bundle.putString(Constants.STATUS, status);
fragment.setArguments(bundle);
return fragment;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
AndroidSupportInjection.inject(this);
binding = getViewDataBinding();
viewModel = ViewModelProviders.of(this, new ReqListViewModel.ModelFactory(getBaseActivity(), server, repository)).get(ReqListViewModel.class);
viewModel.setNavigator(this);
status = getArguments().getString(Constants.STATUS);
viewModel.filterStatus.postValue(status);
if (status.equals(Constants.ALL)) {
loadData(status);
}
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
binding.swipe.setColorSchemeColors(getResources().getColor(R.color.colorPrimary), getResources().getColor(R.color.colorApprovedBg));
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getBaseActivity());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
binding.recyclerView.setLayoutManager(linearLayoutManager);
binding.swipe.setOnRefreshListener(()->loadData(status));
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(getView() != null && isVisibleToUser && !hasLoaded && !status.equals(Constants.ALL)) {
loadData(status);
}
}
private void loadData(String status) {
binding.shimmerViewContainer.startShimmer();
binding.shimmerViewContainer.setVisibility(View.VISIBLE);
final ReqListAdapter pageListAdapter = new ReqListAdapter(viewModel);
viewModel.getReqDataPaged(status).observe(this, pageListAdapter::submitList);
viewModel.getNetworkState().observe(this, networkState -> {
pageListAdapter.setNetworkState(networkState);
binding.setState(networkState);
});
binding.recyclerView.setAdapter(pageListAdapter);
hasLoaded = true;
}
#Override
public void onItemClick(String item) {
Intent intent = new Intent(getBaseActivity(), ReqViewActivity.class);
intent.putExtra(Constants.SID, item);
startActivity(intent);
}
}
In other conditions I succeed if I move the code initReqPageDao to the RoomDatabase class,
but i am confused about sending status for filter
Thank you all for your help, I hope I find the error and a solution

Unable to save ArrayList value in Shared Preference in Andorid

Can any one help me whats wrong in my code
unable to save ArrayList document value in shared Preference
getting null value in Debug of Array List Document
please help me
Thanks in advance
here is my JSON response
{
"errCode": 0,
"message": "Success",
"responseDestinationDocument": [
{
"name": "United Arab Emirates",
"document": [
{
"name": "Passport Front",
"id": "2",
"notes": [
{
"name": "Upload colored passport copies."
},
{
"name": "Passport should be valid 6 months from the date of entry in Sri Lanka."
},
{
"name": "DDDDDDD"
}
]
},
{
"name": "Passport Back",
"id": "3",
"notes": [
{
"name": "Upload colored passport copy."
}
]
},
{
"name": "Photograph",
"id": "4",
"notes": [
{
"name": "Upload photograph with white background"
}
]
}
]
}
]
}
I want to save ArrayList document value in shared Preference
Here is activity code
public class UploadDocumentsActivity extends AppCompatActivity {
private MyCustomAdapter myCustomAdapter;
protected ViewDialog viewDialog;
String destination_id, start_date, end_date, no_of_travellers, destination_name, package_id, radioSexButton, booking_id, count_index;
private List<ResponseBookingDocument> responseBookingDocumentArrayList;
private List<Document> document1ArrayList;
Document document1;
private RecyclerView recyclerView_Identity;
private static final int SELECT_PICTURE = 100;
private static final int STORAGE_PERMISSION_CODE = 123;
final Handler handler = new Handler();
final int delay = 1000; //milliseconds
private ImageView imageView1;
String selectedImagePath;
private Uri filePath_1;
private boolean isOnTag = false;
Bitmap bitmap;
preivate ArrayList<String> nameList = new ArrayList<>();
preivate ArrayList<String> idList = new ArrayList<>();
TextView continueTextView;
private Runnable mToast = new Runnable() {
#Override
public void run() {
// documentRequiredCall();
handler.postDelayed(this, 1000);
}
};
ResponseBookInfo responseBookInfo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload_documents);
viewDialog = new ViewDialog(this);
viewDialog.setCancelable(false);
// Log.e("document1", document1.getId() + "");
try {
document1 = PrefUtils.getDocId(UploadDocumentsActivity.this);
Log.e("document1", document1.getId() + "");
} catch (Exception e) {
e.printStackTrace();
}
Intent i = getIntent();
destination_id = i.getStringExtra("destination_id");
package_id = i.getStringExtra("package_id");
radioSexButton = i.getStringExtra("radioSexButton");
booking_id = i.getStringExtra("booking_id");
count_index = i.getStringExtra("count_index");
Log.e("BookING", booking_id + "");
destination_name = i.getStringExtra("destination_name");
start_date = i.getStringExtra("start_date");
end_date = i.getStringExtra("end_date");
no_of_travellers = i.getStringExtra("no_of_travellers");
recyclerView_Identity = findViewById(R.id.recyclerView_Identity);
continueTextView = findViewById(R.id.continueTextView);
LinearLayoutManager layoutManager = new LinearLayoutManager(UploadDocumentsActivity.this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView_Identity.setLayoutManager(layoutManager);
recyclerView_Identity.setHasFixedSize(true);
continueTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(UploadDocumentsActivity.this, ApplicationFormActivity.class);
i.putExtra("booking_id", booking_id);
i.putExtra("count_index", count_index);
i.putExtra("start_date", start_date);
i.putExtra("end_date", end_date);
startActivity(i);
}
});
documentRequiredCall();
//
Log.e("Values", destination_id + " " + package_id + " " + end_date + " " + no_of_travellers + " " + count_index + "");
}
public void documentRequiredCall() {
Call<DocumentFetchModel> call = RetrofitClient
.getInstance().getApi().documentFetchModel(booking_id, count_index);
showProgressDialog();
call.enqueue(new Callback<DocumentFetchModel>() {
#Override
public void onResponse(Call<DocumentFetchModel> call, retrofit2.Response<DocumentFetchModel> response) {
final DocumentFetchModel documentFetchModel = response.body();
hideProgressDialog();
PrefUtils.setDocId(documentFetchModel.getResponseBookingDocument().get(0).getDocument(), UploadDocumentsActivity.this);
int size = documentFetchModel.getResponseBookingDocument().get(0).getDocument().size();
for (int i = 0; i < size; i++) {
nameList.add(documentFetchModel.getResponseBookingDocument().get(0).getDocument().get(i).getName());
idList.add(documentFetchModel.getResponseBookingDocument().get(0).getDocument().get(i).getId());
}
//here is app preference class saving the values
AppPreference.setNameList(this, nameList);
AppPreference.setIdList(this, idLIst);
if (documentFetchModel.getErrCode().booleanValue() == true) {
responseBookingDocumentArrayList = new ArrayList<ResponseBookingDocument>();
try {
Log.e("Booking_Document", new Gson().toJson(response.body()));
document1ArrayList = documentFetchModel.getResponseBookingDocument().get(0).getDocument();
myCustomAdapter = new MyCustomAdapter(document1ArrayList);
recyclerView_Identity.setAdapter(myCustomAdapter);
myCustomAdapter.notifyDataSetChanged();
} catch (Exception e) {
e.printStackTrace();
}
} else {
Toast.makeText(UploadDocumentsActivity.this, documentFetchModel.getMessage() + "", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<DocumentFetchModel> call, Throwable t) {
hideProgressDialog();
Toast.makeText(UploadDocumentsActivity.this, t.getMessage() + "", Toast.LENGTH_LONG).show();
Log.e("Error", t.getMessage() + "");
}
});
}
protected void hideProgressDialog() {
viewDialog.dismiss();
}
protected void showProgressDialog() {
viewDialog.show();
}
protected void showProgressDialog(String message) {
showProgressDialog();
}
public class MyCustomAdapter extends RecyclerView.Adapter<MyCustomAdapter.MyViewHolder> {
private List<Document> moviesList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textTitle;
public ImageView imageUpload, imageFetch;
private List<Note> noteArrayList;
private MyCustomAdapter2 myCustomAdapter2;
private RecyclerView recyclerView_Identity_Bullets;
public MyViewHolder(View view) {
super(view);
textTitle = view.findViewById(R.id.textTitle);
imageUpload = view.findViewById(R.id.imageUpload);
imageFetch = view.findViewById(R.id.imageFetch);
recyclerView_Identity_Bullets = view.findViewById(R.id.recyclerView_Identity_Bullets);
LinearLayoutManager layoutManager2 = new LinearLayoutManager(UploadDocumentsActivity.this);
layoutManager2.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView_Identity_Bullets.setLayoutManager(layoutManager2);
recyclerView_Identity_Bullets.setHasFixedSize(true);
}
}
public MyCustomAdapter(List<Document> moviesList) {
this.moviesList = moviesList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_upload_document, parent, false);
return new MyCustomAdapter.MyViewHolder(itemView);
}
public void clear() {
int size = this.moviesList.size();
if (size > 0) {
for (int i = 0; i < size; i++) {
this.moviesList.remove(0);
}
this.notifyItemRangeRemoved(0, size);
}
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
final Document datum = moviesList.get(position);
holder.textTitle.setText(datum.getName() + "");
holder.noteArrayList = datum.getNotes();
holder.myCustomAdapter2 = new MyCustomAdapter2(holder.noteArrayList);
holder.recyclerView_Identity_Bullets.setAdapter(holder.myCustomAdapter2);
if (datum.getImageName().equals("")) {
holder.imageFetch.setVisibility(View.GONE);
holder.imageUpload.setVisibility(View.VISIBLE);
holder.imageUpload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(UploadDocumentsActivity.this, datum.getId(), Toast.LENGTH_SHORT).show();
}
});
} else {
holder.imageUpload.setVisibility(View.GONE);
holder.imageFetch.setVisibility(View.VISIBLE);
Picasso.with(UploadDocumentsActivity.this).load(datum.getImageName() + "").into(holder.imageFetch);
}
}
#Override
public int getItemCount() {
return moviesList.size();
}
}
public class MyCustomAdapter2 extends RecyclerView.Adapter<MyCustomAdapter2.MyViewHolder> {
private List<Note> moviesList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textBullet;
public MyViewHolder(View view) {
super(view);
textBullet = view.findViewById(R.id.textBullet);
}
}
public MyCustomAdapter2(List<Note> moviesList) {
this.moviesList = moviesList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_upload_bullets_and_image, parent, false);
return new MyViewHolder(itemView);
}
public void clear() {
int size = this.moviesList.size();
if (size > 0) {
for (int i = 0; i < size; i++) {
this.moviesList.remove(0);
}
this.notifyItemRangeRemoved(0, size);
}
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
final Note datum = moviesList.get(position);
holder.textBullet.setText(" \u25CF " + datum.getName() + "");
Log.e("textBullet", datum.getName() + "");
}
#Override
public int getItemCount() {
return moviesList.size();
}
}
#Override
public void onStart() {
super.onStart();
mToast.run();
}
#Override
public void onStop() {
super.onStop();
handler.removeCallbacks(mToast);
}
}
Here is Model Class
public class DocumentFetchModel {
#SerializedName("errCode")
#Expose
private Boolean errCode;
#SerializedName("message")
#Expose
private String message;
#SerializedName("responseBookingDocument")
#Expose
private List<ResponseBookingDocument> responseBookingDocument = null;
public Boolean getErrCode() {
return errCode;
}
public void setErrCode(Boolean errCode) {
this.errCode = errCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<ResponseBookingDocument> getResponseBookingDocument() {
return responseBookingDocument;
}
public void setResponseBookingDocument(List<ResponseBookingDocument> responseBookingDocument) {
this.responseBookingDocument = responseBookingDocument;
}
}
public class ResponseBookingDocument {
#SerializedName("name")
#Expose
private String name;
#SerializedName("document")
#Expose
private List<Document> document = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Document> getDocument() {
return document;
}
public void setDocument(List<Document> document) {
this.document = document;
}
}
public class DocumentFetchModel {
#SerializedName("errCode")
#Expose
private Boolean errCode;
#SerializedName("message")
#Expose
private String message;
#SerializedName("responseBookingDocument")
#Expose
private List<ResponseBookingDocument> responseBookingDocument = null;
public Boolean getErrCode() {
return errCode;
}
public void setErrCode(Boolean errCode) {
this.errCode = errCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<ResponseBookingDocument> getResponseBookingDocument() {
return responseBookingDocument;
}
public void setResponseBookingDocument(List<ResponseBookingDocument> responseBookingDocument) {
this.responseBookingDocument = responseBookingDocument;
}
}
Here is ComplexPreference
public class ComplexPreferences {
private static ComplexPreferences complexPreferences;
private Context context;
private SharedPreferences preferences;
private SharedPreferences.Editor editor;
private static Gson GSON = new Gson();
Type typeOfObject = new TypeToken<Object>() {
}.getType();
private ComplexPreferences(Context context, String namePreferences, int mode) {
this.context = context;
if (namePreferences == null || namePreferences.equals("")) {
namePreferences = "complex_preferences";
}
preferences = context.getSharedPreferences(namePreferences, mode);
editor = preferences.edit();
}
public static ComplexPreferences getComplexPreferences(Context context,
String namePreferences, int mode) {
// if (complexPreferences == null) {
complexPreferences = new ComplexPreferences(context,
namePreferences, mode);
// }
return complexPreferences;
}
public void putObject(String key, Object object) {
if(object == null){
throw new IllegalArgumentException("object is null");
}
if(key.equals("") || key == null){
throw new IllegalArgumentException("key is empty or null");
}
editor.putString(key, GSON.toJson(object));
}
public void commit() {
editor.commit();
}
public void clearObject() {
editor.clear();
}
public <T> T getObject(String key, Class<T> a) {
String gson = preferences.getString(key, null);
if (gson == null) {
return null;
} else {
try{
return GSON.fromJson(gson, a);
} catch (Exception e) {
throw new IllegalArgumentException("Object storaged with key " + key + " is instanceof other class");
}
}
}
}
Here is PrefUtils Class
public class PrefUtils {
public static DocumentFetchModel getDoc(Context ctx) {
ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(ctx, "get_doc", 0);
DocumentFetchModel currentUser = complexPreferences.getObject("docs", DocumentFetchModel.class);
return currentUser;
}
public static void setDoc(DocumentFetchModel currentUser, Context ctx) {
ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(ctx, "get_doc", 0);
complexPreferences.putObject("docs", currentUser);
complexPreferences.commit();
}
}
you can save list in sharedpreference like this:-
public class AppPreferences {
private static SharedPreferences mPrefs;
private static SharedPreferences.Editor mPrefsEditor;
public static Set<String> getName(Context ctx) {
mPrefs = PreferenceManager.getDefaultSharedPreferences(ctx);
return mPrefs.getStringSet("nameList", null);
}
public static void setName(Context ctx, ArrayList<String> value) {
mPrefs = PreferenceManager.getDefaultSharedPreferences(ctx);
mPrefsEditor = mPrefs.edit();
Set<String> set = new HashSet<>();
set.addAll(value);
mPrefsEditor.putStringSet("nameList", set);
mPrefsEditor.commit();
}
public static void clearNameList(Context ctx) {
mPrefs = PreferenceManager.getDefaultSharedPreferences(ctx);
mPrefsEditor = mPrefs.edit();
Set<String> set = new HashSet<>();
mPrefsEditor.putStringSet("nameList", set);
mPrefsEditor.commit();
}
}
to set list :-
setCamEval(activity, list);
to get list :-
getCamEval(this);

Errors when trying to save strings, ints and spinner values to room persistence database in Android Studio

I'm trying to create a database within my step counting program that is able to save a user's details: Name, Age, Gender, Average Stride Length, Weight and Height in Android Studio. However I keep encountering errors that I am unable to locate or solve. Apologies if it is a rookie mistake; I am not in possession of a great deal of experience for Android Studio or the Room Persistence Library. Here is the code in question:
UserDetails.java:
#Entity(tableName = "user details")
public class UserDetails extends AppCompatActivity {
#NonNull
//each value for the primary key will be assigned a unique,
// automatically generated UserID
#PrimaryKey (autoGenerate = true)
#ColumnInfo(name = "ID")
public int UserID;
#ColumnInfo(name = "Name")
public String UserName;
#ColumnInfo(name = "Age")
public int UserAge;
#ColumnInfo(name = "Gender")
public String UserGender;
#ColumnInfo(name = "Average Stride Length")
public int UserAveStride;
#ColumnInfo(name = "Weight")
public int UserWeight;
#ColumnInfo(name = "Height")
public int UserHeight;
public UserDetails() {
}
#Ignore
public UserDetails(String userName, int userAge, String userGender, int
userAveStride, int userWeight, int userHeight) {
UserName = userName;
UserAge = userAge;
UserGender = userGender;
UserAveStride = userAveStride;
UserWeight = userWeight;
UserHeight = userHeight;
}
public int getUserID() {
return UserID;
}
public void setUserID(int userID) {
UserID = userID;
}
public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
public int getUserAge() {
return UserAge;
}
public void setUserAge(int userAge) {
UserAge = userAge;
}
public String getUserGender() {
return UserGender;
}
public void setUserGender(String userGender) {
UserGender = userGender;
}
public int getUserAveStride() {
return UserAveStride;
}
public void setUserAveStride(int userAveStride) {
UserAveStride = userAveStride;
}
public int getUserWeight() {
return UserWeight;
}
public void setUserWeight(int userWeight) {
UserWeight = userWeight;
}
public int getUserHeight() {
return UserHeight;
}
public void setUserHeight(int userHeight) {
UserHeight = userHeight;
}
#Override
public String toString(){
return new
StringBuilder(UserName).append("\n").append(UserAge).append("\n")
.append(UserGender).append("\n").append(UserAveStride).append("\n")
.append(UserWeight).append("\n").append(UserHeight).toString();
}
DbContent.java
public class DbContent extends AppCompatActivity {
private ListView lstUser;
private FloatingActionButton fab;
//array adapter
List<UserDetails> userList;
ArrayAdapter adapter;
//database
private CompositeDisposable compositeDisposable;
private UserRepository userRepository;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_db_content);
//init
compositeDisposable = new CompositeDisposable();
//init view
lstUser = findViewById(R.id.lstUsers);
fab = findViewById(R.id.fab);
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,
userList);
registerForContextMenu(lstUser);
lstUser.setAdapter(adapter);
//creating database
Database database = Database.getmInstance(this);
userRepository =
UserRepository.getmInstance(UserDataSource.getmInstance(database.userDao()));
//load all data from database
loadData();
//getting values from user inputs
final EditText name = findViewById(R.id.nameInput);
final EditText age = findViewById(R.id.ageInput);
final Spinner gender = findViewById(R.id.genderDropDown);
final EditText aveStride = findViewById(R.id.strideInput);
final EditText weight = findViewById(R.id.weightInput);
final EditText height = findViewById(R.id.heightInput);
//converting to strings
final String nameStr = name.getText().toString();
final String ageStr = age.getText().toString();
final String genderStr = gender.getSelectedItem().toString();
final String aveStrideStr = aveStride.getText().toString();
final String weightStr = weight.getText().toString();
final String heightStr = height.getText().toString();
//converting string to int where needed
final int ageInt = Integer.parseInt(ageStr);
final int aveStrideInt = Integer.parseInt(aveStrideStr);
final int weightInt = Integer.parseInt(weightStr);
final int heightInt = Integer.parseInt(heightStr);
//Event
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Add new
Disposable disposable = (Disposable) io.reactivex
.Observable.create(new ObservableOnSubscribe<Object>() {
#Override
public void subscribe(ObservableEmitter<Object> e) throws
Exception {
UserDetails userDetails = new UserDetails(nameStr,
ageInt,
genderStr, aveStrideInt, weightInt, heightInt);
userRepository.insertUser(userDetails);
e.onComplete();
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Consumer() {
#Override
public void accept(Object o) throws Exception {
Toast.makeText(DbContent.this,
"Data added", Toast.LENGTH_SHORT).show();
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
Toast.makeText(DbContent.this,
"" + throwable.getMessage(), Toast.LENGTH_SHORT).show();
}
//Refreshing data
}, new Action() {
#Override
public void run() throws Exception {
loadData();
}
}
);
}
});
}
private void loadData() {
//Using RXJava
Disposable disposable = userRepository.getAllDetails()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Consumer<List<UserDetails>>() {
#Override
public void accept(List<UserDetails> userDetails) throws Exception {
OnGetAllDetailsSuccess(userDetails);
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
Toast.makeText(DbContent.this, ""+throwable.getMessage(), Toast.LENGTH_SHORT).show();
}
});
compositeDisposable.add(disposable);
}
private void OnGetAllDetailsSuccess(List<UserDetails> userDetails) {
userList.clear();
userList.addAll(userDetails);
adapter.notifyDataSetChanged();
}
}
Database.java
#android.arch.persistence.room.Database(entities = {UserDetails.class},
version = DATABASE_VERSION)
public abstract class Database extends RoomDatabase {
public static final int DATABASE_VERSION=1;
public static final String DATABASE_NAME ="Database-Room";
public abstract UserDao userDao();
private static Database mInstance;
public static Database getmInstance(Context context)
{
if (mInstance == null){
mInstance = Room.databaseBuilder(context,Database.class,DATABASE_NAME)
.fallbackToDestructiveMigration()
.build();
}
return mInstance;
}
}
UserDataSource.java
public class UserDataSource implements IUserDataSource {
private UserDao userDao;
private static UserDataSource mInstance;
public UserDataSource(UserDao userDao) {
this.userDao = userDao;
}
public static UserDataSource getmInstance(UserDao userDao) {
if(mInstance == null){
mInstance = new UserDataSource(userDao);
}
return mInstance;
}
#Override
public Flowable<UserDetails> getUserById(int userId) {
return userDao.getUserById(userId);
}
#Override
public Flowable<List<UserDetails>> getAllDetails() {
return userDao.getAllDetails();
}
#Override
public void insertUser(UserDetails... userDetails) {
userDao.insertUser(userDetails);
}
#Override
public void updateUser(UserDetails... userDetails) {
userDao.updateUser(userDetails);
}
#Override
public void deleteUser(UserDetails userDetails) {
userDao.deleteUser(userDetails);
}
}
UserRepository.java
public class UserRepository implements IUserDataSource {
private IUserDataSource mLocalDataSource;
private static UserRepository mInstance;
public UserRepository(IUserDataSource mLocalDataSource) {
this.mLocalDataSource = mLocalDataSource;
}
public static UserRepository getmInstance(IUserDataSource mLocalDataSource) {
if(mInstance == null){
mInstance = new UserRepository(mLocalDataSource);
}
return mInstance;
}
#Override
public Flowable<UserDetails> getUserById(int userId) {
return mLocalDataSource.getUserById(userId);
}
#Override
public Flowable<List<UserDetails>> getAllDetails() {
return mLocalDataSource.getAllDetails();
}
#Override
public void insertUser(UserDetails... userDetails) {
mLocalDataSource.insertUser(userDetails);
}
#Override
public void updateUser(UserDetails... userDetails) {
mLocalDataSource.updateUser(userDetails);
}
#Override
public void deleteUser(UserDetails userDetails) {
mLocalDataSource.deleteUser(userDetails);
}
}
UserDao.java
#Dao
public interface UserDao {
#Query("SELECT * FROM `user details` WHERE id=:userId")
Flowable<UserDetails> getUserById(int userId);
#Query("SELECT * FROM `user details`")
Flowable<List<UserDetails>> getAllDetails();
#Insert
void insertUser(UserDetails... userDetails);
#Update
void updateUser(UserDetails... userDetails);
#Delete
void deleteUser(UserDetails userDetails);
}
IUserDataSource.java
public interface IUserDataSource {
Flowable<UserDetails> getUserById(int userId);
Flowable<List<UserDetails>> getAllDetails();
void insertUser(UserDetails... userDetails);
void updateUser(UserDetails... userDetails);
void deleteUser(UserDetails userDetails);
}
The errors are:
Cannot figure out how to save this field into database. You can consider adding a type converter for it.
Cannot find getter for field.
Cannot find setter for field.
Cannot figure out how to read this field from a cursor.
Cannot find getter for field.
Cannot find setter for field.
I appreciate any help greatly as I have spent a number of hours trying to fix this and this project is one fifth of my grade; it is due in soon and I need to spend time finishing other features and testing it rather than spending hours trying to fix errors. Thank you.
I believe that the errors you are trying to describe are similar to :-
The cause of these would be that you have made your UserDetails a subclass of the AppCompatActivity class by encoding extends AppCompatActivity
Instead of :-
#Entity(tableName = "user details")
public class UserDetails extends AppCompatActivity { ..........
You should have :-
#Entity(tableName = "user details")
public class UserDetails { ........
Note the dots represent the rest of the code, they are not intended to be coded, they are for the sake of brevity.

Data from server is not displaying on screen

So am working with retrofit and rxjava for my application.so am using the #GET annociation to pull my blog details from the server that include blog_title, blog_content, blog_thumbnail etc and all this parameter are within an array called blog_post.
I have my APIClient:
public class ApiClient {
private static final String STAGING_BASE_URL = "https://watchnollywood.ml/api/";
private static ApiClient instance;
private ApiService apiService;
private ApiClient(){
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
// set your desired log level
// TODO: 21/03/2017 when going live change the log level to NONE, to enhance performance
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
// add logging as last interceptor
httpClient.addInterceptor(logging); // <-- this is the important line for logging requests!
final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
//final Retrofit retrofit = new Retrofit.Builder().baseUrl(STAGING_BASE_URL).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create(gson)).client(httpClient.build()).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(STAGING_BASE_URL)
.client(httpClient.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
apiService = retrofit.create(ApiService.class);
}
public static ApiClient getInstance(){
if(instance == null){
instance = new ApiClient();
}
return instance;
}
//API CALL FOR LOGIN
public Observable<UserItem> login(String email, String password){
return apiService.signIn(email,password);
}
//API CALL FOR SIGNUP
public Observable<StatusItem> signup(String email, String password, String full_name, String phone){
return apiService.signUp(email, password,phone,full_name);
}
//API CALL FOR BLOG DETAILS
public Observable<BlogResponse> blog_post(){
return apiService.blog_post();
}
}
ApiService:
public interface ApiService {
#FormUrlEncoded
#POST("signin")
Observable<UserItem> signIn(#Field("email") String email, #Field("password") String password);
#FormUrlEncoded
#POST("signup")
Observable<StatusItem> signUp(#Field("full_name")String full_name, #Field("phone") String phone, #Field("email") String email, #Field("password") String password);
#GET("blog")
Observable<BlogResponse> blog_post();
}
pojo classes:
public class BlogItem {
private int thumbNail;
private String title;
private String summary;
public int getThumbNail() {
return thumbNail;
}
public void setThumbNail(#DrawableRes int thumbNail) {
this.thumbNail = thumbNail;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
}
public class BlogResponse {
private BlogItem[] blogItems;
public BlogItem[] getBlogItems() {
return blogItems;
}
public void setBlogItems(BlogItem[] blogItems) {
this.blogItems = blogItems;
}
}
I have a recyclerview that will hold all the information that will be coming from the server. But the problem is that when I run it I get a log response in my RUN terminal but nothing is showing on the app screen.
this is my FragmentClass that holds the information from the server:
BlogFragment:
public class BlogFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private String mParam1;
private RecyclerView recyclerView;
private BlogAdapter adapter;
private List<BlogItem> blogItems;
private View view;
public BlogFragment() {
// Required empty public constructor
}
public static BlogFragment newInstance(String param1) {
BlogFragment fragment = new BlogFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_blog, container, false);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
recyclerView = (RecyclerView) view.findViewById(R.id.blog_posts_list);
setUpViews();
}
private void setUpViews() {
blogItems = new ArrayList<>();
adapter = new BlogAdapter(blogItems);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
BlogPost();
// populateLists();
}
private void BlogPost() {
ApiClient.getInstance().blog_post().observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.newThread()).subscribe(new DisposableObserver<BlogResponse>() {
#Override
public void onNext(BlogResponse value) {
BlogItem blogItem = new BlogItem();
blogItem.setTitle(blogItem.getTitle().toString());
blogItem.setSummary(blogItem.getSummary().toString());
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
BlogItem blogItem = new BlogItem();
blogItem.setTitle("blog_title");
blogItem.setSummary("blog_content");
}
});
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
}
/*
private void populateLists() {
int dummyPostArraySize = 10;
for (int i = 0; i < dummyPostArraySize; i++) {
BlogItem blogItem = new BlogItem();
blogItem.setTitle("Post title " + i+1);
blogItem.setThumbNail(isEven(i) ? R.drawable.profile_image : 0);
blogItem.setSummary(getString(isEven(i) ? R.string.summary2 : R.string.summary1));
blogItems.add(blogItem);
}
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
}*/
private boolean isEven(int position) {
return (position & 1) == 0;
}
}
Adapter class
public class BlogAdapter extends RecyclerView.Adapter<BlogViewHolder> {
private List<BlogItem> blogItems;
public BlogAdapter(List<BlogItem> blogItems) {
this.blogItems = blogItems;
}
#Override
public BlogViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.blog_post_item,
parent, false);
return new BlogViewHolder(view);
}
#Override
public void onBindViewHolder(BlogViewHolder holder, int position) {
BlogItem blogItem = blogItems.get(position);
holder.bindModel(blogItem);
}
#Override
public int getItemCount() {
return blogItems == null ? (0) : blogItems.size();
}
}
View Holder class
public class BlogViewHolder extends RecyclerView.ViewHolder {
private ImageView cover;
private TextView title;
private TextView summary;
public BlogViewHolder(View itemView) {
super(itemView);
cover = (ImageView) itemView.findViewById(R.id.post_thumbnail);
title = (TextView) itemView.findViewById(R.id.post_title);
summary = (TextView) itemView.findViewById(R.id.post_summary);
}
public void bindModel(BlogItem blogItem) {
if (blogItem.getThumbNail() == 0) {
cover.setVisibility(View.GONE);
} else {
cover.setImageResource(blogItem.getThumbNail());
}
title.setText(Html.fromHtml(blogItem.getTitle()));
summary.setText(blogItem.getSummary());
}
}
What am I not doing right. Someone Please Help!!!
In the private void BlogPost() { method, you create BlogItems but then don't do anything with it. You probably forgot to add them to the blogItems list.
In addition, the call to adapter.notifyItemRangeChanged in that method happens way before the sequence receives data but you don't call that after each blogItem or when all blog items have arrived - the observer is on a complete different execution path than the outer BlogPost() method.
Edit spelled out:
#Override
public void onNext(BlogResponse value) {
for (BlogItem responseItem : value.getBlogItems()) {
BlogItem blogItem = new BlogItem();
blogItem.setTitle(responseItem.getTitle().toString());
blogItem.setSummary(responseItem.getSummary().toString());
blogItems.add(blogItem);
}
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
BlogItem blogItem = new BlogItem();
blogItem.setTitle("blog_title");
blogItem.setSummary("blog_content");
blogItems.add(blogItem);
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
}

Categories

Resources