I have a problem with transfering data from retrofit to room. I downloaded data from the API but when i try getting data in room database I receive the error :
" Caused by: java.lang.ClassCastException: java.util.ArrayList cannot
be cast to".
Debug shows me on error in
newsDao.insert((News) news);
AND
.subscribe(new Consumer<List<News>>()
Here is my code.
import android.arch.persistence.room.Room;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import java.util.List;
import burtsev.a.k.news.Model.News;
import burtsev.a.k.news.Retrofit.NewsAPI;
import burtsev.a.k.news.Retrofit.RetrofitClient;
import burtsev.a.k.news.Room.NewsDao;
import burtsev.a.k.news.Room.NewsDatabase;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import retrofit2.Retrofit;
public class Splash extends AppCompatActivity {
public static Splash instance;
public NewsDatabase newsDatabase;
NewsAPI newsAPI;
CompositeDisposable compositeDisposable = new CompositeDisposable();
NewsDao newsDao;
public static Splash getInstance() {
return instance;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
newsDatabase = Room.databaseBuilder(getApplicationContext(),
NewsDatabase.class, "database")
.allowMainThreadQueries()
.build();
newsDao = newsDatabase.newsDao();
Retrofit retrofit = RetrofitClient.getInstance();
newsAPI = retrofit.create(NewsAPI.class);
fetchData();
}
private void fetchData() {
compositeDisposable.add(newsAPI.getNews().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<List<News>>() {
#Override
public void accept(List<News> news) throws Exception {
Intent intent = new Intent(Splash.this, NewsListFragment.class);
// intent.putExtra("news", (Serializable) news);
newsDao.insert((News) news);
startActivity(intent);
}
}));
}
#Override
protected void onStop() {
compositeDisposable.clear();
super.onStop();
}
public NewsDatabase getNewsDatabase() {
return newsDatabase;
}
}
you are trying to insert list but, you are trying to cast it to an object.
so news is not a News model. it is a List<News>. If you want to insert all your news objects. you can try foreach or you can create a new function inside your DAO which will insert all list at once.
foreach;
for(News anews: news){
newsDao.insert(anews);
}
to insert at once. new function inside your DAO class should be;
#Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAllNews(List<News> news);
in your subscibe you need to use;
newsDao.insertAllNews(news);
Related
getViewBinding() method does not override method from its superclass BaseActivity<T extends ViewBinding>
MentorChatActivity.java
package com.ocr.firebaseoc.ui.chat;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.firebase.firestore.Query;
import com.ocr.firebaseoc.databinding.ActivityMentorChatBinding;
import com.ocr.firebaseoc.manager.ChatManager;
import com.ocr.firebaseoc.manager.UserManager;
import com.ocr.firebaseoc.model.Message;
import com.ocr.firebaseoc.ui.BaseActivity;
public class MentorChatActivity extends BaseActivity<ActivityMentorChatBinding> implements MentorChatAdapter.Listener {
private MentorChatAdapter mentorChatAdapter;
private String currentChatName;
private static final String CHAT_NAME_ANDROID = "android";
private static final String CHAT_NAME_BUG = "bug";
private static final String CHAT_NAME_FIREBASE = "firebase";
private UserManager userManager = UserManager.getInstance();
private ChatManager chatManager = ChatManager.getInstance();
#Override
protected ActivityMentorChatBinding getViewBinding() {
return ActivityMentorChatBinding.inflate(getLayoutInflater());
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
configureRecyclerView(CHAT_NAME_ANDROID);
setupListeners();
}
private void setupListeners(){
// Chat buttons
binding.androidChatButton.setOnClickListener(view -> { this.configureRecyclerView(CHAT_NAME_ANDROID); });
binding.firebaseChatButton.setOnClickListener(view -> { this.configureRecyclerView(CHAT_NAME_FIREBASE); });
binding.bugChatButton.setOnClickListener(view -> { this.configureRecyclerView(CHAT_NAME_BUG); });
}
// Configure RecyclerView
private void configureRecyclerView(String chatName){
//Track current chat name
this.currentChatName = chatName;
//Configure Adapter & RecyclerView
this.mentorChatAdapter = new MentorChatAdapter(
generateOptionsForAdapter(chatManager.getAllMessageForChat(this.currentChatName)),
Glide.with(this), this);
mentorChatAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
binding.chatRecyclerView.smoothScrollToPosition(mentorChatAdapter.getItemCount()); // Scroll to bottom on new messages
}
});
binding.chatRecyclerView.setLayoutManager(new LinearLayoutManager(this));
binding.chatRecyclerView.setAdapter(this.mentorChatAdapter);
}
// Create options for RecyclerView from a Query
private FirestoreRecyclerOptions<Message> generateOptionsForAdapter(Query query){
return new FirestoreRecyclerOptions.Builder<Message>()
.setQuery(query, Message.class)
.setLifecycleOwner(this)
.build();
}
public void onDataChanged() {
// Show TextView in case RecyclerView is empty
binding.emptyRecyclerView.setVisibility(this.mentorChatAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
}
BaseActivity.java
package com.ocr.firebaseoc.ui;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewbinding.ViewBinding;
import com.ocr.firebaseoc.databinding.ActivityMentorChatBinding;
/**
* Base Activity class that allow to manage all the common code for the activities
* #param <T> Should be the type of the viewBinding of your activity see more here
*/
public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActivity {
abstract T getViewBinding();
protected T binding;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initBinding();
}
/**
* Initialise the binding object and the layout of the activity
*/
private void initBinding(){
binding = getViewBinding();
View view = binding.getRoot();
setContentView(view);
}
}
Error message:
Class 'MentorChatActivity' must either be declared abstract or implement abstract method 'getViewBinding()' in 'BaseActivity'
Method does not override method from its superclass
Can someone please explain what went wrong ?
here's my project's github link
abstract T getViewBinding() is a package private, you can't override in other package. MentorChatActivity is in other package that's why its throwing error.
Make your abstract method public,
abstract public T getViewBinding(), or move all classes to same package.
I used Room Architecture for a simple database to display a list of city names.
The database is working but my only issue is that the database list only shows after I tap on the Edit text field. I have attached the respective code and some screenshots for better understanding.
I am sure it is some minor logical error that I've done. Can anyone help?
Thanks in advance.
Locations Activity
package com.example.smweather;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Toast;
import java.util.List;
public class LocationsActivity extends AppCompatActivity {
private LocationViewModel locationViewModel;
AutoCompleteTextView trialedCity;
String[] trialCityNames;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_locations);
setTitle("Locations");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
trialedCity = findViewById(R.id.aedCity);
trialCityNames = getResources().getStringArray(R.array.sample_city_names);
ArrayAdapter<String> sampleCityListAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, trialCityNames);
trialedCity.setAdapter(sampleCityListAdapter);
trialedCity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
trialedCity.setCursorVisible(true);
}
});
RecyclerView locationRecyclerView = findViewById(R.id.location_recycler_view);
locationRecyclerView.setLayoutManager(new LinearLayoutManager(this));
locationRecyclerView.setHasFixedSize(true);
final LocationAdapter adapter = new LocationAdapter();
locationRecyclerView.setAdapter(adapter);
locationViewModel = new ViewModelProvider(this,
ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication()))
.get(LocationViewModel.class);
locationViewModel.getAllLocations().observe(this, new Observer<List<Location>>() {
#Override
public void onChanged(List<Location> locations) {
adapter.submitList(locations);
}
});
adapter.setOnLocationClickListener(new LocationAdapter.OnLocationClickListener(){
#Override
public void onLocationClick(Location location) {
String trialvalue = location.getStrlocation();
Intent resultIntent = new Intent();
resultIntent.putExtra("trialValue",trialvalue);
setResult(RESULT_OK,resultIntent);
finish();
}
});
// TODO: 12-08-2020 swipe gesture to delete
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.LEFT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull
RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
locationViewModel.delete(adapter.getLocationAt(viewHolder.getAdapterPosition()));
Toast.makeText(LocationsActivity.this, "Location deleted",
Toast.LENGTH_SHORT).show();
}
}).attachToRecyclerView(locationRecyclerView);
}
public void trialdata(View view) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(myApi.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
myApi trialapi = retrofit.create(myApi.class);
Call<Example> exampleCall =
trialapi.getinfo(trialedCity.getText().toString().trim(),MainActivity.openWeatherapiKey);
exampleCall.enqueue(new Callback<Example>() {
#Override
public void onResponse(Call<Example> call, Response<Example> response) {
if (response.code() == 404) {
Toast.makeText(LocationsActivity.this, "Invalid City",
Toast.LENGTH_SHORT).show();
} else if (response.code() == 429) {
Toast.makeText(LocationsActivity.this, "Your account is temporary blocked due to
exceeding of requests limitation of your subscription type.",
Toast.LENGTH_SHORT).show();
} else if (!response.isSuccessful()) {
Toast.makeText(LocationsActivity.this, "Error code: " + response.code(),
Toast.LENGTH_SHORT).show();
} else {
String trialvalue = trialedCity.getText().toString().trim();
Intent resultIntent = new Intent();
resultIntent.putExtra("trialValue",trialvalue);
Location location = new Location(trialvalue);
locationViewModel.insert(location);
setResult(RESULT_OK,resultIntent);
finish();
}
}
#Override
public void onFailure(Call<Example> call, Throwable t) {
Toast.makeText(LocationsActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public boolean onSupportNavigateUp() {
finish();
return true;
}
}
ViewModel Class
package com.example.smweather;
import android.app.Application;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
public class LocationViewModel extends AndroidViewModel {
private LocationRepository repository;
private LiveData<List<Location>> allLocations;
public LocationViewModel(#NonNull Application application) {
super(application);
repository = new LocationRepository(application);
allLocations = repository.getAllLocations();
}
public void insert(Location location) {
repository.insert(location);
}
public void update(Location location) {
repository.update(location);
}
public void delete(Location location) {
repository.delete(location);
}
public void deleteAllLocations() {
repository.deleteAllLocations();
}
public LiveData<List<Location>> getAllLocations() {
return allLocations;
}
}
In the first image The list of database should show below the search button
The list only shows when the editText field is clicked
Please see the above pictures for better understanding.
I am not completely sure, but maybe you should call adapter.notifyDataSetChanged() in your Observer.
I'm trying to implement pull to refresh with MVVM (and a recyclerview) yet I don't understand how I'm supposed to fetch new data. Inital load up of the app is fine as I'm just observing the livedata from the view model when it's created, but how do I query for more data?
MainActivity.java
package com.example.simplenews;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.example.simplenews.adapters.NewsArticleAdapter;
import com.example.simplenews.adapters.RecyclerItemClickListener;
import com.example.simplenews.models.Article;
import com.example.simplenews.models.NewsResponse;
import com.example.simplenews.repositories.NewsAPI;
import com.example.simplenews.repositories.NewsRepository;
import com.example.simplenews.viewmodels.NewsViewModel;
import com.victor.loading.rotate.RotateLoading;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import timber.log.Timber;
public class MainActivity extends AppCompatActivity {
private RecyclerView newsRecyclerView;
private NewsArticleAdapter newsAdapter;
private NewsAPI NewsAPI;
private ArrayList<Article> newsArticles = new ArrayList<>();
private RotateLoading rotateLoadingIndicator;
private SwipeRefreshLayout swipeRefreshLayout;
private NewsViewModel newsViewModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Planting timber debug tree here because this joint refuses to work when planted in the application class
Timber.plant(new Timber.DebugTree());
swipeRefreshLayout = findViewById(R.id.swipe_refresh_layout);
newsRecyclerView = findViewById(R.id.newsRecyclerView);
rotateLoadingIndicator = findViewById(R.id.rotate_loading_indicator);
// Getting and setting up the viewmodel
newsViewModel = new ViewModelProvider(this).get(NewsViewModel.class);
newsViewModel.initNewsViewModel();
// Setting up the observer
newsViewModel.getNewsRepositoryQuery().observe(this, newsResponse -> {
ArrayList<Article> freshNewsArticles = (ArrayList<Article>) newsResponse.getArticles();
newsArticles.addAll(freshNewsArticles);
newsAdapter.notifyDataSetChanged();
});
initReyclerView();
// This is not the way to do recyclerview click listeners but this will suffice for now
newsRecyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(this, newsRecyclerView, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Article article = newsArticles.get(position);
Uri uri = Uri.parse(article.getUrl());
Intent webIntent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(webIntent);
}
#Override
public void onLongItemClick(View view, int position) {
}
})
);
// Configure the refreshing colors
swipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.colorPrimary));
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
newsViewModel.getNewHeadlines().observe(MainActivity.this, new Observer<NewsResponse>() {
#Override
public void onChanged(NewsResponse newsResponse) {
if (newsResponse.getArticles() != null) {
refreshNewsRecyclerView(newsResponse.getArticles());
swipeRefreshLayout.setRefreshing(false);
}
swipeRefreshLayout.setRefreshing(false);
Timber.d("the articles in the refresh callback were null");
}
});
}
});
}
/*
* Helper method that refreshes topHeadlinesRecyclerView with new articles
* #param: list of new article objects from a network request
* */
private void refreshNewsRecyclerView(List<Article> freshArticles) {
newsRecyclerView.setVisibility(View.INVISIBLE);
showLoadingIndicator();
newsAdapter.clearNewsArticles();
newsAdapter.addAll(freshArticles);
newsRecyclerView.setVisibility(View.VISIBLE);
hideLoadingIndicator();
newsAdapter.notifyDataSetChanged();
}
/*
* Helper method to show the loading indicator
* */
private void showLoadingIndicator() {
rotateLoadingIndicator.setVisibility(View.VISIBLE);
rotateLoadingIndicator.start();
}
/*
* Helper method to hide loading indicator
* */
private void hideLoadingIndicator() {
rotateLoadingIndicator.stop();
rotateLoadingIndicator.setVisibility(View.GONE);
}
/*
* Helper method to setup the recyclerView
* */
private void initReyclerView() {
if (newsAdapter == null) {
showLoadingIndicator();
newsAdapter = new NewsArticleAdapter(newsArticles, this);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
newsRecyclerView.setLayoutManager(layoutManager);
newsRecyclerView.setAdapter(newsAdapter);
hideLoadingIndicator();
} else {
newsAdapter.notifyDataSetChanged();
}
}
}
NewsViewModel
public class NewsViewModel extends ViewModel {
private MutableLiveData<NewsResponse> mutableLiveData;
private NewsRepository newsRepository;
// When a viewmodel object is created fetch the data needed for the activitiy
public void initNewsViewModel() {
if (mutableLiveData != null) {
return;
}
newsRepository = NewsRepository.getInstance();
mutableLiveData = newsRepository.getTopHeadlines();
}
public MutableLiveData<NewsResponse> getNewsRepositoryQuery() {
return mutableLiveData;
}
public MutableLiveData<NewsResponse> getNewHeadlines() {
MutableLiveData<NewsResponse> response = newsRepository.getTopHeadlines();
return response;
}
}
News Repository
public class NewsRepository {
private static NewsRepository newsRepository;
private NewsAPI newsAPI;
private List<Article> freshArticles;
public static NewsRepository getInstance() {
if (newsRepository == null) {
newsRepository = new NewsRepository();
}
return newsRepository;
}
/*
* Private constructor because nobody should be creating this object direcly
* */
private NewsRepository() {
newsAPI = RetrofitClient.getRetrofitInstance().create(NewsAPI.class);
}
public MutableLiveData<NewsResponse> getTopHeadlines() {
MutableLiveData<NewsResponse> topHeadlines = new MutableLiveData<>();
newsAPI.getRootJSONObject().enqueue(new Callback<NewsResponse>() {
#Override
public void onResponse(Call<NewsResponse> call, Response<NewsResponse> response) {
if (response.isSuccessful()) {
topHeadlines.setValue(response.body());
Timber.d("Network call was succesful here is the response code " + response.code());
} else {
Timber.d("Network call was unsuccesful " + response.code());
}
}
#Override
public void onFailure(Call<NewsResponse> call, Throwable t) {
Timber.d("Network call completely failed lol");
topHeadlines.setValue(null);
}
});
return topHeadlines;
}
}
You can simply make a function which reset value of MutableLiveData
For example on swipe call viewmodel.resetNewsHeadlines() and in resetNewsHeadlines() method simple set value to null and recall mutableLiveData = newsRepository.getTopHeadlines(); again
I have written this simple example to test paging library and observe changes to PagedList using LiveData but it notifies the observer only once, when the LiveData<PagedList<Integer>> object is created. I load more data using a button in my activity and pagedList object is loaded correctly but changes are not observed. here's the code for my activity:
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.arch.paging.PagedList;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MainViewModel mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
Button b = findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PagedList<Integer> s = mainViewModel.getIntegers().getValue();
s.loadAround(s.size());
}
});
mainViewModel.setUpPaging(1);
mainViewModel.getIntegers().observe(this, new Observer<PagedList<Integer>>() {
#Override
public void onChanged(#Nullable PagedList<Integer> integers) {
//logging some text
Log.i("MyLog","new list Observed");
}
});
}
}
here's my ViewModel class:
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.ViewModel;
import android.arch.paging.LivePagedListBuilder;
import android.arch.paging.PagedList;
public class MainViewModel extends ViewModel {
LiveData<PagedList<Integer>> integers;
public LiveData<PagedList<Integer>> getIntegers() {
return integers;
}
public void setUpPaging(Integer startFrom){
integers = new LivePagedListBuilder<Integer,Integer>(IntegersDataSource.randomNumbersStartingFrom(startFrom),
new PagedList.Config.Builder()
.setPageSize(5)
.setEnablePlaceholders(false)
.build()).build();
}
}
and here's my DataSource which for simplicity only generate random integers :
import android.arch.paging.DataSource;
import android.arch.paging.PageKeyedDataSource;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class IntegersDataSource extends PageKeyedDataSource<Integer,Integer> {
private Integer initialInt;
private final Integer BOUND = 300;
public IntegersDataSource(Integer initialInt) {
this.initialInt = initialInt;
}
#Override
public void loadInitial(#NonNull LoadInitialParams<Integer> params, #NonNull LoadInitialCallback<Integer, Integer> callback) {
Random r = new Random();
Integer i = r.nextInt(BOUND - 1) + 1;
List<Integer> l = new ArrayList<>();
l.add(i);
callback.onResult(l,initialInt-1, initialInt+1);
}
#Override
public void loadBefore(#NonNull LoadParams<Integer> params, #NonNull LoadCallback<Integer, Integer> callback) {
Random r = new Random();
Integer i = r.nextInt(BOUND - 1) + 1;
List<Integer> l = new ArrayList<>();
l.add(i);
callback.onResult(l, params.key-1);
}
#Override
public void loadAfter(#NonNull LoadParams<Integer> params, #NonNull LoadCallback<Integer, Integer> callback) {
Random r = new Random();
Integer i = r.nextInt(BOUND - 1) + 1;
List<Integer> l = new ArrayList<>();
l.add(i);
callback.onResult(l, params.key+1);
}
private static class RandomsFactory extends DataSource.Factory{
Integer srartFrom;
public RandomsFactory(Integer startFrom) {
this.srartFrom = startFrom;
}
#Override
public DataSource create() {
return new IntegersDataSource(srartFrom);
}
}
public static DataSource.Factory<Integer, Integer> randomNumbersStartingFrom(Integer startFrom) {
return new RandomsFactory(startFrom);
}
}
and this is in my build gradle :
implementation "android.arch.paging:runtime:1.0.0-rc1"
I keep pushing the button multiple times but only one time it is observed(for creation time).
PagedListAdapter doesn’t reflect changed item itself. To put it another way, PagedList is immutable. you should call invalidate() on the current DataSource when an update occurs. A new PagedList / DataSource pair will be created via LivePagedListBuilder and It will be passed through LiveData to observers when the current DataSource is invalidated.
Try this code.
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PagedList<Integer> s = mainViewModel.getIntegers().getValue();
s.getDataSource().invalidate();
}
});
Please check out this demo app.
https://github.com/jungilhan/cheese-aac-paging-sample/tree/item_based_paging
Even though every thing is working properly and registration is happening. Retrofit on Response don't get called but onFailure gets called. Call.isexecutted returns true.
I am showing the model class and registrationFragment where the error occured. This is taking a lot time. So thanks in advance for help
RegistrationFragment.java
package com.example.milan.hospital;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* A simple {#link Fragment} subclass.
*/
public class RegistrationFragment extends Fragment {
private EditText Name,UserName, UserPassword;
private Button BnRegister;
public RegistrationFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_registration, container, false);
Name = view.findViewById(R.id.txt_name);
UserName = view.findViewById(R.id.txt_user_name);
UserPassword = view.findViewById(R.id.txt_password);
BnRegister = view.findViewById(R.id.bn_register);
BnRegister.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
performRegistration();
}
});
return view;
}
public void performRegistration()
{
String name = Name.getText().toString();
String username = UserName.getText().toString();
String password = UserPassword.getText().toString();
Call<User> call = MainActivity.apiInterface.performRegistration(name,username,password);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
if(response.body().getResponse().equals("ok"))
{
MainActivity.prefConfig.displayToast("Registration success...");
}
else if(response.body().getResponse().equals("exist"))
{
MainActivity.prefConfig.displayToast("User already exist....");
}
else if(response.body().getResponse().equals("error"))
{
MainActivity.prefConfig.displayToast("Something went wrong...");
}
}
#Override
public void onFailure(Call<User> call, Throwable t) {
}
});
Name.setText("");
UserPassword.setText("");
UserName.setText("");
}
}
User.java
package com.example.milan.hospital;
import com.google.gson.annotations.SerializedName;
public class User {
#SerializedName("response")
private String Response;
#SerializedName("name")
private String Name;
public String getResponse() {
return Response;
}
public String getName() {
return Name;
}
}
MainActivity.java
package com.example.milan.hospital;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity implements LoginFragment.OnLoginFormActivityListener{
public static PrefConfig prefConfig;
public static ApiInterface apiInterface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
prefConfig = new PrefConfig(this);
apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
if(findViewById(R.id.fragment_container) != null)
{
if(savedInstanceState != null)
{
return;
}
if(prefConfig.readLoginStatus())
{
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container,new WelcomeFragment()).commit();
}
else
{
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container,new LoginFragment()).commit();
}
}
}
#Override
public void performRegister() {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new RegistrationFragment()).addToBackStack(null).commit();
}
#Override
public void performLogin(String name) {
}
}
ApiInterface.java
package com.example.milan.hospital;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface ApiInterface
{
#GET("register.php")
Call<User> performRegistration(#Query("name") String Name,#Query("user_name") String UserName,#Query("user_password") String UserPassword);
#GET("login.php")
Call<User> performUserLogin(#Query("user_name") String UserName,#Query("user_password") String UserPassword);
}
I think performRegistration() in ApiInterface.java should have an annotation of #POST rather than #GET since registration is the act of posting data rather than getting. Give it a try once.
change the ApiClient to this. As there was a well known problem of retrofit while reading json. to resolve we have initialize gson object ourself
public class ApiClient
{
public static final String BASE_URL = "http://10.0.3.2/loginapp/";
public static Retrofit retrofit = null;
public static Retrofit getApiClient()
{
Gson gson = new GsonBuilder()
.setLenient()
.create();
if(retrofit == null)
{
retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).build();
}
return retrofit;
}
}