I am trying to load data into my recyclerview via url okhttp calls, and I am receiving the following error:
"java.lang.ClassCastException: SearchActivity cannot be cast to SearchForBarbershop$BarbershopRequesterResponse"
Here are the classes.
SearchActivity:
public class SearchActivity extends AppCompatActivity {
private RecyclerAdapter mAdapter;
private RecyclerView mRecyclerView;
private LinearLayoutManager mLinearLayoutManager;
private ArrayList<Barbershop> barbershopList;
private SearchForBarbershop searchForBarbershop;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
mLinearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLinearLayoutManager);
barbershopList = new ArrayList<>();
mAdapter = new RecyclerAdapter(barbershopList);
mRecyclerView.setAdapter(mAdapter);
setRecyclerViewScrollListener();
searchForBarbershop = new SearchForBarbershop(this);
}
#Override
protected void onStart() {
super.onStart();
if (barbershopList.size() == 0) {
requestShop();
}
}
private int getLastVisibleItemPosition() {
return mLinearLayoutManager.findLastVisibleItemPosition();
}
private void setRecyclerViewScrollListener() {
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
int totalItemCount = mRecyclerView.getLayoutManager().getItemCount();
if (!searchForBarbershop.isLoadingData() && totalItemCount == getLastVisibleItemPosition() + 1) {
requestShop();
}
}
});
}
private void requestShop() {
try {
searchForBarbershop.getBarbershop();
} catch (IOException e) {
e.printStackTrace();
}
}
//#Override
public void receivedNewShop(final Barbershop newBarbershop) {
runOnUiThread(new Runnable() {
#Override
public void run() {
barbershopList.add(newBarbershop);
mAdapter.notifyItemInserted(barbershopList.size());
}
});
}
}
SearchForBarbershop:
public class SearchForBarbershop {
public interface BarbershopRequesterResponse {
void receivedNewBarbershop(Barbershop barbershop);
}
private BarbershopRequesterResponse barbershopRequesterResponse;
private OkHttpClient client;
private boolean isLoadingData;
public boolean isLoadingData() { return isLoadingData; }
public SearchForBarbershop (Activity listeningActivity) {
client = new OkHttpClient();
isLoadingData = false;
barbershopRequesterResponse = (BarbershopRequesterResponse) listeningActivity;
}
public void getBarbershop() throws IOException {
String url = "http://pubapi.yp.com/search-api/search/devapi/search?searchloc=30043&term=barbers&format=json&sort=distance&radius=50&listingcount=20&key=gmj3x7mhsh";
Request request = new Request.Builder().url(url).build();
isLoadingData = true;
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
isLoadingData = false;
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
try {
JSONObject object = new JSONObject(response.body().string());
Barbershop receivedShop = new Barbershop(object);
barbershopRequesterResponse.receivedNewBarbershop(receivedShop);
isLoadingData = false;
} catch (JSONException e) {
isLoadingData = false;
e.printStackTrace();
}
}
});
}
}
Barbershop:
public class Barbershop{
private String name;
private String city;
public Barbershop(JSONObject barbershopJSON) {
try {
JSONArray businessArray = barbershopJSON.getJSONObject("searchResult").getJSONObject("searchListings").getJSONArray("searchListing");
for(int i = 0; i < businessArray.length(); i++) {
//Parse JSON and assign to variables
JSONObject business_object_1 = businessArray.getJSONObject(i);
String primaryc = business_object_1.getString("primaryCategory");
//Check to make sure the main category is "Barbers"
if((primaryc).equals("Barbers")) {
name = business_object_1.getString("businessName");
city = business_object_1.getString("city");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public String getCity() {
return city;
}
public String getName() {
return name;
}
}
RecyclerAdapter:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ShopHolder> {
private ArrayList<Barbershop> mbarbershops;
public RecyclerAdapter(ArrayList<Barbershop> barbershops) {
mbarbershops = barbershops;
}
#Override
public RecyclerAdapter.ShopHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View inflatedView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cardview_barber_search, parent, false);
return new ShopHolder(inflatedView);
}
#Override
public void onBindViewHolder(RecyclerAdapter.ShopHolder holder, int position) {
Barbershop itemBarbershop = mbarbershops.get(position);
holder.bindShop(itemBarbershop);
}
#Override
public int getItemCount() {
return 0;
}
public static class ShopHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView mName;
private TextView mCity;
public ShopHolder(View view) {
super(view);
mName = (TextView) view.findViewById(R.id.textViewName);
mCity = (TextView) view.findViewById(R.id.textViewCity);
view.setOnClickListener(this);
}
#Override
public void onClick(View v) {
}
public void bindShop(Barbershop barbershop) {
mName.setText(barbershop.getName());
mCity.setText(barbershop.getCity());
}
}
}
It can't be cast because it doesn't implement that interface. Your commented-out #override statement should be a clue for you here.
Change it to:
public class SearchActivity extends AppCompatActivity
implements SearchForBarbershop.BarbershopRequesterResponse {
....
And don't forget to remove the comment for method you implemented:
#Override
public void receivedNewShop(final Barbershop newBarbershop) {
....
I think you need change constructor SearchForBarbershop
BarbershopRequesterResponse listener;
Context context
public SearchForBarbershop (Context context,BarbershopRequesterResponse listener) {
client = new OkHttpClient();
isLoadingData = false;
this.context = context;
this.listener = listener;
}
And change in SearchActivity
searchForBarbershop = new SearchForBarbershop(SearchActivity.this, this);
Related
I am training to work with api and the problem arose that when scrolling the RecyclerView, I need the data to be added, namely, "page" is added, and thus the content is added.
I have achieved that before reaching the end of the list, the "onReachEndListener" method is triggered, but I cannot understand the implementation of adding to the sheet. PLEASE HELP ME!
public class MainActivity extends AppCompatActivity {
private SwitchMaterial switchMaterial;
private TextView textViewPopularity, textViewTopRated;
private RecyclerView recyclerViewPosters;
private MovieAdapter movieAdapter;
private MainViewModel viewModel;
private ProgressBar progressBar;
private static final int LOADER_ID = 122;
private LoaderManager loaderManager;
private static int page = 1;
private static String methodOfSort;
private static boolean isLoaning = true;
private static String lang;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.itemMain:
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
break;
case R.id.itemFavourite:
Intent i = new Intent(this, FavouriteActivity.class);
startActivity(i);
break;
}
return super.onOptionsItemSelected(item);
}
private int getColumnCount() {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = (int) (displayMetrics.widthPixels / displayMetrics.density);
return width / 185 > 2 ? width / 2 : 2;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lang = Locale.getDefault().getLanguage();
viewModel = new ViewModelProvider(this).get(MainViewModel.class);
recyclerViewPosters = findViewById(R.id.recyclerViewPosters);
switchMaterial = findViewById(R.id.switchSort);
textViewPopularity = findViewById(R.id.textViewPopularity);
textViewTopRated = findViewById(R.id.textViewTopRated);
progressBar = findViewById(R.id.progressBarLoading);
movieAdapter = new MovieAdapter();
recyclerViewPosters.setLayoutManager(new GridLayoutManager(this, getColumnCount()));
recyclerViewPosters.setAdapter(movieAdapter);
switchMaterial.setChecked(true);
myOnClick();
LiveData<List<Movie>> moviesFromLiveData = viewModel.getMovies();
moviesFromLiveData.observe(this, new Observer<List<Movie>>() {
#Override
public void onChanged(#Nullable List<Movie> movies) {
movieAdapter.setMovies(movies);
}
});
}
private void myOnClick() {
switchMaterial.setOnCheckedChangeListener((compoundButton, b) -> {
page = 1;
setMethodOfSort(b);
});
switchMaterial.setChecked(false);
textViewPopularity.setOnClickListener(view -> {
setMethodOfSort(false);
switchMaterial.setChecked(false);
});
textViewTopRated.setOnClickListener(view -> {
setMethodOfSort(true);
switchMaterial.setChecked(true);
});
movieAdapter.setOnPosterClickListener(position -> {
Movie movie = movieAdapter.getMovies().get(position);
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
intent.putExtra("id", movie.getId());
startActivity(intent);
});
movieAdapter.setOnReachEndListener(() -> {
if (!isLoaning){
viewModel.deleteAllMovies();
progressBar.setVisibility(View.VISIBLE);
viewModel.loadDataImage(lang, methodOfSort, Integer.toString(page));
Log.d("isLoaning", Integer.toString(page));
}
});
recyclerViewPosters.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (!recyclerView.canScrollVertically(1)) {
Log.d("isLoaning", Integer.toString(page));
LiveData<List<Movie>> moviesFromLiveData = viewModel.getMovies();
moviesFromLiveData.observe(MainActivity.this, new Observer<List<Movie>>() {
#Override
public void onChanged(#Nullable List<Movie> movies) {
viewModel.insertMovie(movies);
movieAdapter.addMovies(movies);
page++;
isLoaning = false;
}
});
}
}
});
}
private void setMethodOfSort(boolean b){
if(b) {
methodOfSort = SORT_BY_TOP_RATED;
Log.d("setMethodOfSort", methodOfSort);
textViewPopularity.setTextColor(getResources().getColor(R.color.white));
textViewTopRated.setTextColor(getResources().getColor(R.color.teal_200));
}
else {
methodOfSort = SORT_BY_POPULARITY;
Log.d("setMethodOfSort", methodOfSort);
textViewPopularity.setTextColor(getResources().getColor(R.color.teal_200));
textViewTopRated.setTextColor(getResources().getColor(R.color.white));
}
viewModel.loadData(lang, methodOfSort ,Integer.toString(page));
}
Model:
public class MainViewModel extends AndroidViewModel {
private static MovieDatabase database;
private LiveData<List<Movie>> movies;
private LiveData<List<FavouriteMovie>> favouriteMovies;
private LiveData<String> methodOfSort;
private CompositeDisposable compositeDisposable;
private MutableLiveData<Throwable> errors;
public static final String SMALL_POSTER_SIZE = "w185";
private static final String KEY_POSTER_PATH = "poster_path";
public static final String SORT_BY_POPULARITY = "popularity.desc";
public static final String SORT_BY_TOP_RATED = "vote_average.desc";
public static final int POPULARITY = 0;
public static final int TOP_RATED = 1;
public MainViewModel(#NonNull Application application) {
super(application);
database = MovieDatabase.getInstance(getApplication());
movies = database.movieDao().getAllMovies();
favouriteMovies = database.movieDao().getAllFavouriteMovies();
errors = new MutableLiveData<>();
}
public LiveData<Throwable> getErrors() {
return errors;
}
public void clearErrors() {
errors.setValue(null);
}
public void loadData(String lang, String sort, String page) {
ApiFactory apiFactory = ApiFactory.getInstance();
ApiService apiService = apiFactory.getApiService();
compositeDisposable = new CompositeDisposable();
Disposable disposable = apiService.getMovieResponse("32f91e104228c0c9ff3630899838e82e",
lang,
sort,
"1000",
page)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<MovieResponse>() {
#Override
public void accept(MovieResponse movieResponse) throws Exception {
deleteAllMovies();
insertMovie(movieResponse.getMovies());
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
errors.setValue(throwable);
}
});
compositeDisposable.add(disposable);
}
public void loadDataImage(String lang, String sort, String page) {
ApiFactory apiFactory = ApiFactory.getInstance();
ApiService apiService = apiFactory.getApiService();
compositeDisposable = new CompositeDisposable();
Disposable disposable = apiService.getMovieResponse(
"32f91e104228c0c9ff3630899838e82e",
lang,
sort,
"1000",
page)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<MovieResponse>() {
#Override
public void accept(MovieResponse movieResponse) throws Exception {
insertMovie(movieResponse.getMovies());
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
errors.setValue(throwable);
}
});
compositeDisposable.add(disposable);
}
public Movie getMovieById(int id) {
try {
return new GetMovieTask().execute(id).get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public FavouriteMovie getFavouriteMovieById(int id) {
try {
return new GetFavouriteMovieTask().execute(id).get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public LiveData<List<FavouriteMovie>> getFavouriteMovies() {
return favouriteMovies;
}
public void deleteAllMovies() {
new DeleteMoviesTask().execute();
}
#SuppressWarnings("unchecked")
public void insertMovie(List<Movie> movie) {
new InsertTask().execute(movie);
}
public void deleteMovie(Movie movie) {
new DeleteTask().execute(movie);
}
public LiveData<List<Movie>> getMovies() {
return movies;
}
public void insertFavouriteMovie(FavouriteMovie movie) {
new InsertFavouriteTask().execute(movie);
}
public void deleteFavouriteMovie(FavouriteMovie movie) {
new DeleteFavouriteTask().execute(movie);
}
private static class DeleteFavouriteTask extends AsyncTask<FavouriteMovie, Void, Void> {
#Override
protected Void doInBackground(FavouriteMovie... movies) {
if (movies != null && movies.length > 0) {
database.movieDao().deleteFavouriteMovie(movies[0]);
}
return null;
}
}
private static class InsertFavouriteTask extends AsyncTask<FavouriteMovie, Void, Void> {
#Override
protected Void doInBackground(FavouriteMovie... movies) {
if (movies != null && movies.length > 0) {
database.movieDao().insertFavouriteMovie(movies[0]);
}
return null;
}
}
private static class DeleteTask extends AsyncTask<Movie, Void, Void> {
#Override
protected Void doInBackground(Movie... movies) {
if (movies != null && movies.length > 0) {
database.movieDao().deleteMovie(movies[0]);
}
return null;
}
}
private static class InsertTask extends AsyncTask<List<Movie>, Void, Void> {
#Override
protected Void doInBackground(List<Movie>... movies) {
if (movies != null && movies.length > 0) {
database.movieDao().insertMovie(movies[0]);
}
return null;
}
}
private static class DeleteMoviesTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... integers) {
database.movieDao().deleteAllMovies();
return null;
}
}
private static class GetMovieTask extends AsyncTask<Integer, Void, Movie> {
#Override
protected Movie doInBackground(Integer... integers) {
if (integers != null && integers.length > 0) {
return database.movieDao().getMovieById(integers[0]);
}
return null;
}
}
private static class GetFavouriteMovieTask extends AsyncTask<Integer, Void, FavouriteMovie> {
#Override
protected FavouriteMovie doInBackground(Integer... integers) {
if (integers != null && integers.length > 0) {
return database.movieDao().getFavouriteMovieById(integers[0]);
}
return null;
}
}
#Override
protected void onCleared() {
compositeDisposable.dispose();
super.onCleared();
}
}
Adapter:
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder> {
private List<Movie> movies;
private OnPosterClickListener onPosterClickListener;
private OnReachEndListener onReachEndListener;
private onStartLoadingListener onStartLoadingListener;
public MovieAdapter(){
movies = new ArrayList<>();
}
public interface OnPosterClickListener{
void OnPosterClick(int position);
}
public interface OnReachEndListener{
void onReachEnd();
}
public interface onStartLoadingListener{
void onStartLoading();
}
public void setOnStartLoadingListener(onStartLoadingListener onStartLoadingListener) {
this.onStartLoadingListener = onStartLoadingListener;
}
public void setOnPosterClickListener(OnPosterClickListener onPosterClickListener) {
this.onPosterClickListener = onPosterClickListener;
}
public void setOnReachEndListener(OnReachEndListener onReachEndListener) {
this.onReachEndListener = onReachEndListener;
}
#NonNull
#Override
public MovieViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_item, parent, false);
return new MovieViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MovieViewHolder holder, int position) {
if (movies.size() >= 20 && position > movies.size() - 4 && onReachEndListener != null){
onReachEndListener.onReachEnd();
}
Movie movie = movies.get(position);
Picasso.get().load(movie.getPosterPath()).into(holder.imageViewSmallPoster);
}
#Override
public int getItemCount() {
return movies.size();
}
class MovieViewHolder extends RecyclerView.ViewHolder{
private ImageView imageViewSmallPoster;
public MovieViewHolder(#NonNull View itemView) {
super(itemView);
imageViewSmallPoster = itemView.findViewById(R.id.imageViewSmallPoster);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(onPosterClickListener != null){
onPosterClickListener.OnPosterClick(getAdapterPosition());
}
}
});
}
}
public void clear(){
this.movies.clear();
notifyDataSetChanged();
}
public List<Movie> getMovies() {
return movies;
}
public void addMovies(List<Movie> movies){
this.movies.addAll(movies);
notifyDataSetChanged();
}
public void setMovies(List<Movie> movies) {
this.movies = movies;
notifyDataSetChanged();
}
}
i know its a duplicate question for so many fellows but i have tried all possible solutions which were given by community members but none of them helped me so i am posting this question as i am stuck with this error.I urge all the members please look at my code before marking it as duplicate.
i am using the recyclerview inside a fragment.
this is my fragment class:-
public class BuyOrders extends Fragment {
private Boolean isConnected = true;
private Socket mSocket;
LinearLayoutManager mLinearLayoutManager;
private RecyclerView mRecyclerView;
private ArrayList<BuyOrderHistory> mMessages = new ArrayList<BuyOrderHistory>();
private RecyclerView.Adapter mAdapter;
private static final String TAG = "BuyOrderHistoryFragment";
public BuyOrders() {
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mAdapter = new BuyOrderHistoryAdapter(mMessages, context);
if (context instanceof Activity) {
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
AppController app = (AppController) getActivity().getApplication();
mSocket = app.getSocket();
mSocket.connect();
mSocket.on(Socket.EVENT_CONNECT, onConnect);
mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
mSocket.on("connection_successfull", onConnect);
mSocket.on("buy_orders_data", onBuyOrdersData);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragments_buyorders, container, false);
return v;
}
#Override
public void onDestroy() {
super.onDestroy();
mSocket.off(Socket.EVENT_CONNECT, onConnect);
mSocket.off(Socket.EVENT_DISCONNECT, onDisconnect);
mSocket.off(Socket.EVENT_CONNECT_ERROR, onConnectError);
mSocket.off(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
mSocket.off("connection_successfull", onConnect);
mSocket.off("buy_orders_data", onBuyOrdersData);
mSocket.disconnect();
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mLinearLayoutManager = new LinearLayoutManager(getActivity());
mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView = (RecyclerView) view.findViewById(R.id.rv_buyorder);
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mRecyclerView.setAdapter(mAdapter);
}
private Emitter.Listener onConnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (!isConnected) {
JSONObject data = (JSONObject)args[0];
Log.d(TAG, String.valueOf(data));
mSocket.emit("fetch_buy_orders",sendFetchBuyOrderRequest(""));
Log.i(TAG, "connected");
Toast.makeText(getActivity().getApplicationContext(),
R.string.connect, Toast.LENGTH_LONG).show();
isConnected = true;
}
}
});
}
};
protected String sendFetchBuyOrderRequest(String s) {
String pageno = "1";
String recordperpage = "10";
String userid = "22";
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("page_no:", pageno );
jsonObject.put("records_per_page", recordperpage);
jsonObject.put("user_id:", userid);
return jsonObject.toString();
}catch (Exception e){
e.printStackTrace();
}
return s;
}
private Emitter.Listener onBuyOrdersData = new Emitter.Listener() {
#Override
public void call(final Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
Log.v("Data Coming From Server", String.valueOf(data));
String volume;
String bid;
String total;
try {
volume = data.getString("volume");
bid = data.getString("bid");
total = data.getString("total");
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
return;
}
addData(volume,bid,total);
}
});
}
};
protected void addData(String volume, String bid, String total){
mMessages.add(new BuyOrderHistory.Builder(BuyOrderHistory.RECEIVER)
.volume(volume).bid(bid).total(total).build());
mAdapter.notifyItemInserted(mMessages.size() - 1);
scrollToBottom();
}
private void scrollToBottom() {
mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
}
protected Emitter.Listener onDisconnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Log.i(TAG, "disconnected");
isConnected = false;
Toast.makeText(getActivity().getApplicationContext(),
R.string.disconnect, Toast.LENGTH_LONG).show();
}
});
}
};
protected Emitter.Listener onConnectError = new Emitter.Listener() {
#Override
public void call(Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Log.e(TAG, "Error connecting");
Toast.makeText(getActivity().getApplicationContext(),
R.string.error_connect, Toast.LENGTH_LONG).show();
}
});
}
};
}
Below is my Adapter class:-
public class BuyOrderHistoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
ArrayList<BuyOrderHistory> arrayList;
Context context;
private int RECEIVER = BuyOrderHistory.RECEIVER;
public BuyOrderHistoryAdapter(ArrayList<BuyOrderHistory> arrayList,Context context){
this.arrayList = arrayList;
this.context = context;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = null;
RecyclerView.ViewHolder vh = null;
if (viewType == RECEIVER){
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_buyorders, parent,false);
vh = new ReceivedDataHolder(v);
}
return vh;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == RECEIVER){
((ReceivedDataHolder)holder).volume.setText(arrayList.get(position).getmVolume());
((ReceivedDataHolder)holder).bid.setText(arrayList.get(position).getmBid());
((ReceivedDataHolder)holder).total.setText(arrayList.get(position).getmTotal());
}
}
#Override
public int getItemCount() {
return arrayList == null ? 0 : arrayList.size();
}
#Override
public int getItemViewType(int position) {
if(arrayList.get(position).getmType() == RECEIVER){
}
return RECEIVER;
}
private class ReceivedDataHolder extends RecyclerView.ViewHolder{
public TextView volume, bid, total;
public ReceivedDataHolder(View itemView) {
super(itemView);
volume = (TextView) itemView.findViewById(R.id.tv_buyvolume);
bid = (TextView) itemView.findViewById(R.id.tv_buybid);
total = (TextView) itemView.findViewById(R.id.tv_buytotal);
}
}
Try :
mMessages.add(new BuyOrderHistory.Builder(BuyOrderHistory.RECEIVER)
.volume(volume).bid(bid).total(total).build());
mAdapter = new BuyOrderHistoryAdapter(mMessages, getContext());
mAdapter.notifyItemInserted(mMessages.size() - 1);
mLinearLayoutManager = new LinearLayoutManager(getActivity());
mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView = (RecyclerView) view.findViewById(R.id.rv_buyorder);
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
Tutorial :
tutorial 1
tutorial 2
tutorial 3
1) "No adapter attached; skipping layout" is not an error, but rather an info from the RecyclerView informing you that there is no adapter at this time. See the dispatchLayout() method from the RV source code
2) To solve your issue: add an the following method to your adapter class:
public void add(BuyOrderHistory item){
arrayList.add(item);
notifyItemInserted(arrayList.indexOf(item));
}
Then call this method on your Adapter instance as soon as you have a BuyOrderHistory object created and all fields set. You could of course re-init and re-set your adapter each time you got new data, I would not recommend that however.
I have a recyclerview that display news.
News is composed by name_news,image_news,time_news.
I am getting the data from mysqldatabse.
This is my adapter class:
public class PostAdapter2 extends RecyclerView.Adapter<PostAdapter2.ViewHolder>{
public Context c;
public FragmentManager mContext;
public ArrayList<News_data> original_items = new ArrayList<>();
public ArrayList<News_data> filtered_items = new ArrayList<>();
public ArrayList<Simplenews_data> original_items2 = new ArrayList<>();
public ArrayList<Simplenews_data> filtered_items2 = new ArrayList<>();
// ItemFilter mFilters = new ItemFilter();
public PostAdapter2(Context c, ArrayList<News_data> postList) {
this.c = c;
this.original_items = postList;
this.filtered_items = postList;
}
public PostAdapter2(FragmentManager mContext, ArrayList<Simplenews_data> postList) {
this.mContext = mContext;
this.original_items2 = postList;
this.filtered_items2 = postList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_news, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
try {
final Simplenews_data post = filtered_items2.get(position);
PicassoClient.downloadImage(c, post.getImage_simplenews(), holder.image_news);
holder.txt_news_title.setText(post.getName_simplenews());
holder.txt_date.setText(post.getTime_simplenews());
holder.setItemClickListener(new ItemClickListener() {
#Override
public void onItemClick() {
Bundle x = new Bundle();
x.putString("news_title", post.getName_simplenews());
x.putString("news", post.getDesc_simplenews());
x.putString("image",post.getImage_simplenews());
x.putString("time",post.getTime_simplenews());
x.putString("date",post.getDate_simplenews());
Fragment descriptionFragment = new DescriptionFragment();
FragmentTransaction transaction = mContext.beginTransaction();
descriptionFragment.setArguments(x);
transaction.replace(R.id.framelayout, descriptionFragment).addToBackStack(null).commit();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public int getItemCount() {
return filtered_items2.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ItemClickListener itemClickListener;
TextView txt_news_title,txt_date;
ImageView image_news;
public ViewHolder(View itemView) {
super(itemView);
txt_news_title = (TextView) itemView.findViewById(R.id.txt_news_title);
txt_date = (TextView) itemView.findViewById(R.id.txt_timedate);
image_news = (ImageView) itemView.findViewById(R.id.image_news);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
try {
this.itemClickListener.onItemClick();
}catch (Exception e)
{
e.printStackTrace();
}
}
public void setItemClickListener(ItemClickListener itemClickListener)
{
this.itemClickListener=itemClickListener;
}
}
}
I am using a PHP interface to add news.
The getTime_simplenews() contains the news sumbmitted time format as : 14:00
So i want to display the immediate news in Top of recyclerview not under the previous news.
Thanks a lot.
UPDATED :
public class Simplenews_data {
int id_simplenews;
String name_simplenews,image_simplenews,desc_simplenews,time_simplenews,date_simplenews;
public String getDate_simplenews() {
return date_simplenews;
}
public void setDate_simplenews(String date_simplenews) {
this.date_simplenews = date_simplenews;
}
public String getTime_simplenews() {
return time_simplenews;
}
public void setTime_simplenews(String time_simplenews) {
this.time_simplenews = time_simplenews;
}
public int getId_simplenews() {
return id_simplenews;
}
public void setId_simplenews(int id_simplenews) {
this.id_simplenews = id_simplenews;
}
public String getName_simplenews() {
return name_simplenews;
}
public void setName_simplenews(String name_simplenews) {
this.name_simplenews = name_simplenews;
}
public String getImage_simplenews() {
return image_simplenews;
}
public void setImage_simplenews(String image_simplenews) {
this.image_simplenews = image_simplenews;
}
public String getDesc_simplenews() {
return desc_simplenews;
}
public void setDesc_simplenews(String desc_simplenews) {
this.desc_simplenews = desc_simplenews;
}
Fragment Code:
public void parseJson2(String response) {
try {
JSONArray array = new JSONArray(response);
JSONObject jsonObject = null;
post_array2.clear();
Simplenews_data p;
for (int i = 0; i < array.length(); i++) {
jsonObject = array.getJSONObject(i);
int id_simplenews = jsonObject.getInt("id_simplenews");
String name_simplenews = jsonObject.getString("name_simplenews");
String image_simplenews = jsonObject.getString("image_simplenews");
String desc_simplenews = jsonObject.getString("desc_simplenews");
String time_simplenews = jsonObject.getString("time_simplenews");
String date_simplenews = jsonObject.getString("date_simplenews");
p = new Simplenews_data();
p.setId_simplenews(id_simplenews);
p.setName_simplenews(name_simplenews);
p.setImage_simplenews(image_simplenews);
p.setDesc_simplenews(desc_simplenews);
p.setTime_simplenews(time_simplenews);
p.setDate_simplenews(date_simplenews);
post_array2.add(p);
}
} catch (JSONException e) {
swipeRefreshLayout.setRefreshing(false);
e.printStackTrace();
}
adapter = new PostAdapter2(getFragmentManager(), post_array2);
recycler_post.setAdapter(adapter);
swipeRefreshLayout.setRefreshing(false);
}
I have updated your model class and implemented Comparable to it
public class Simplenews_data implements Comparable<Simplenews_data> {
int id_simplenews;
String name_simplenews,image_simplenews,desc_simplenews,time_simplenews,date_simplenews;
public String getDate_simplenews() {
return date_simplenews;
}
public void setDate_simplenews(String date_simplenews) {
this.date_simplenews = date_simplenews;
}
public String getTime_simplenews() {
return time_simplenews;
}
public void setTime_simplenews(String time_simplenews) {
this.time_simplenews = time_simplenews;
}
public int getId_simplenews() {
return id_simplenews;
}
public void setId_simplenews(int id_simplenews) {
this.id_simplenews = id_simplenews;
}
public String getName_simplenews() {
return name_simplenews;
}
public void setName_simplenews(String name_simplenews) {
this.name_simplenews = name_simplenews;
}
public String getImage_simplenews() {
return image_simplenews;
}
public void setImage_simplenews(String image_simplenews) {
this.image_simplenews = image_simplenews;
}
public String getDesc_simplenews() {
return desc_simplenews;
}
public void setDesc_simplenews(String desc_simplenews) {
this.desc_simplenews = desc_simplenews;
}
#Override
public int compareTo(MyObject o) {
Date newDate = formatDateTime(o.getTime_simplenews(), "HH:mm", "YYYY-MM-DD HH:mm");
Date inputDate = formatDateTime(getTime_simplenews(), "HH:mm", "YYYY-MM-DD HH:mm");
return inputDate.compareTo(newDate);
}
public Date formatDateTime(String date, String fromFormat, String toFormat) {
Date d = null;
try {
d = new SimpleDateFormat(fromFormat, Locale.US).parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return new SimpleDateFormat(toFormat, Locale.US).parse(d);
}
}
Sort the list using below code
Collections.sort(yourList);
I have a problem, when i swipe to refresh the data, the first swipe is ok but after that every swipe reload and add the same data over and over again, by the end i have a list with same items over and over... I'm using a loader.
I tried to clear before but i don't understand what's wrong with my code, if someone could explain it to me. Thank You.
Here my code :
public abstract class NewsFragment extends Fragment implements LoaderManager.LoaderCallbacks<ArrayList<Articles>> {
protected ItemAdapter mArticleAdapter;
protected RecyclerView mRecyclerView;
protected NewsFragment.OnNewSelectedInterface mListener;
protected RecyclerView.LayoutManager mManager;
protected SwipeRefreshLayout mSwipeRefreshLayout;
protected LoaderManager mLoaderManager;
private boolean mStateSaved;
private static final int NEWS_LOAD_ID = 1;
public static final String KEY_LIST = "key_list";
public interface OnNewSelectedInterface {
void onListNewSelected(int index, ArrayList<Articles> articles);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.list_present_news, container, false);
mListener = (NewsFragment.OnNewSelectedInterface) getActivity();
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeContainer);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
mManager = new LinearLayoutManager(getActivity());
mArticleAdapter = new ItemAdapter(getActivity(), new ArrayList<Articles>(), mListener);
mLoaderManager = getLoaderManager();
mStateSaved = mArticleAdapter.isStateSaved();
mRecyclerView.setAdapter(mArticleAdapter);
mRecyclerView.setLayoutManager(mManager);
getData();
refreshData();
if(!isNetworkAvailable())alertUserAboutError();
setDivider();
return view;
}
private void setDivider() {
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView
.getContext(), DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
}
private void getData() {
getLoaderManager().initLoader(NEWS_LOAD_ID, null, this).forceLoad();
}
private void alertUserAboutError() {
AlertDialogFragment alertDialogFragment = new AlertDialogFragment();
alertDialogFragment.show(getActivity().getFragmentManager(), "error_dialog");
}
protected abstract String[] getUrl();
private boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager)
getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if (networkInfo != null && networkInfo.isConnected()) {
isAvailable = true;
}
return isAvailable;
}
private void refreshData() {
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mArticleAdapter.clear();
mSwipeRefreshLayout.setRefreshing(false);
}
});
mSwipeRefreshLayout.setColorSchemeResources(
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
}
#Override
public Loader<ArrayList<Articles>> onCreateLoader(int id, Bundle args) {
return new NewsLoader(getActivity(), getUrl());
}
#Override
public void onLoadFinished(Loader<ArrayList<Articles>> loader, ArrayList<Articles> data) {
if (data != null && !data.isEmpty()) {
mArticleAdapter.addAll(data);
}
}
#Override
public void onLoaderReset(Loader<ArrayList<Articles>> loader) {
mArticleAdapter.clear();
}
}
My loader class :
public class NewsLoader extends AsyncTaskLoader<ArrayList<Articles>>{
private ArrayList<Articles> mArticlesArrayList;
private String[] mUrl;
public NewsLoader(Context context, String[] url) {
super(context);
mUrl = url;
}
#Override
public ArrayList<Articles> loadInBackground() {
OkHttpClient mClient = new OkHttpClient();
for (String aMUrl : mUrl) {
Request mRequest = new Request.Builder().url(aMUrl).build();
try {
Response response = mClient.newCall(mRequest).execute();
try {
if (response.isSuccessful()) {
String json = response.body().string();
getMultipleUrls(json);
}
} catch (IOException | JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return mArticlesArrayList;
}
private void getMultipleUrls(String jsonData) throws JSONException {
if (mArticlesArrayList == null) {
mArticlesArrayList = getArticleForecast(jsonData);
} else {
mArticlesArrayList.addAll(getArticleForecast(jsonData));
}
}
private ArrayList<Articles> getArticleForecast(String jsonData) throws JSONException {
JSONObject forecast = new JSONObject(jsonData);
JSONArray articles = forecast.getJSONArray("articles");
ArrayList<Articles> listArticles = new ArrayList<>(articles.length());
for (int i = 0; i < articles.length(); i++) {
JSONObject jsonArticle = articles.getJSONObject(i);
Articles article = new Articles();
String urlImage = jsonArticle.getString("urlToImage");
article.setTitle(jsonArticle.getString("title"));
article.setDescription(jsonArticle.getString("description"));
article.setImageView(urlImage);
article.setArticleUrl(jsonArticle.getString("url"));
listArticles.add(i, article);
}
return listArticles;
}
}
My Adapter class :
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ArticleViewHolder> {
private static final String TAGO = ItemAdapter.class.getSimpleName();
private final NewsFragment.OnNewSelectedInterface mListener;
private ArrayList<Articles> mArticlesList;
private Context mContext;
private int lastPosition = -1;
private boolean mStateSaved = false;
public boolean isStateSaved() {
return mStateSaved;
}
public void setStateSaved(boolean stateSaved) {
mStateSaved = stateSaved;
}
public ItemAdapter(Context context, ArrayList<Articles> articles, NewsFragment.OnNewSelectedInterface listener){
mContext = context;
mArticlesList = articles;
mListener = listener;
}
#Override
public ArticleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_card_view, parent, false);
ArticleViewHolder articleViewHolder = new ArticleViewHolder(view);
articleViewHolder.setIsRecyclable(false);
return articleViewHolder;
}
#Override
public void onBindViewHolder(ArticleViewHolder holder, int position) {
holder.bindArticle(mArticlesList.get(holder.getAdapterPosition()));
setAnimation(holder.itemView, holder.getAdapterPosition());
}
private void setAnimation(View viewToAnimate, int position) {
if (position > lastPosition) {
Animation animation = AnimationUtils.loadAnimation(viewToAnimate.getContext(), android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
#Override
public int getItemCount() {
return mArticlesList.size();
}
public void clear() {
mArticlesList.clear();
notifyDataSetChanged();
}
public void addAll(ArrayList<Articles> articles) {
mArticlesList.addAll(articles);
notifyDataSetChanged();
}
protected class ArticleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private ImageView mImageView;
private TextView mTitleTextView, mDescriptionTextView;
private FloatingActionButton mSaveButton;
private ArticleViewHolder(View itemView) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.photoImageView);
mTitleTextView = (TextView) itemView.findViewById(R.id.titleWithoutImage);
mDescriptionTextView = (TextView) itemView.findViewById(R.id.descriptionTextView);
mSaveButton = (FloatingActionButton) itemView.findViewById(R.id.floatingActionButton);
itemView.setOnClickListener(this);
}
private void bindArticle(final Articles article) {
Glide.with(mContext).load(article.getImageView()).into(mImageView);
mTitleTextView.setText(article.getTitle());
mDescriptionTextView.setText(article.getDescription());
if(mDescriptionTextView.getText().equals("")){
mDescriptionTextView.setVisibility(View.GONE);
}
mSaveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
insertArticle(article);
article.setStateSaved(true);
}
});
Log.v(TAGO, "Item id : " + getItemId()
+ "Item count : " + getItemCount()
+ "Item position : " + getAdapterPosition()
+ String.valueOf(article.isStateSaved()));
}
private void insertArticle(Articles articles) {
String title = articles.getTitle();
String description = articles.getDescription();
String url = articles.getArticleUrl();
ContentValues contentValues = new ContentValues();
contentValues.put(ArticleContract.ArticleEntry.COLUMN_TITLE_ARTICLE, title);
contentValues.put(ArticleContract.ArticleEntry.COLUMN_DESCRIPTION_ARTICLE, description);
contentValues.put(ArticleContract.ArticleEntry.COLUMN_URL_ARTICLE, url);
Uri uri = mContext.getContentResolver().insert(ArticleContract.ArticleEntry.CONTENT_URI, contentValues);
if(uri == null) {
Log.v(TAGO, "Error");
} else Toast.makeText(mContext, "Article Saved", Toast.LENGTH_SHORT).show();
}
#Override
public void onClick(View view) {
mListener.onListNewSelected(getLayoutPosition(), mArticlesList);
}
}
}
You are using ViewHolder#setIsRecyclable incorrectly; this method is meant to be used to prevent a ViewHolder from being recycled only while changes are being made to it. According to the documentation:
Calls to setIsRecyclable() should always be paired (one call to
setIsRecyclabe(false) should always be matched with a later call to
setIsRecyclable(true)).
This means none of your ViewHolder objects will be recycled, effectively making the use of a RecyclerView worthless, and preventing it from reusing the views when you attempt to bind new objects to your RecyclerView.
So, in short, remove that line of code.
I noticed a few other small issues with your adapter code as well, which can cause a multitude headaches in the future; so I took the liberty of highlighting some of the changes I would make.
Just for my own sanity, I will refer to your Articles class as Article.
It is usually not a good idea to pass around your Context all over the place. The View passed to your ViewHolder already has a reference to a Context, so you can use that instead.
As for the insertArticle() code, the Activity should be handling this anyway. So you can pass the Article back to the Activity by passing a listener to your Adapter (and subsequently, each ViewHolder) instead of the Context.
You should also consider using the DiffUtil class instead of just calling notifyDataSetChanged(); it is much more efficient. Just make sure your Article class is implementing equals() and hashCode() or it will not work.
I didn't include the animation code (that can easily be added back in) or the saved state code (mostly because I don't know what you were trying to do).
public class ArticleAdapter extends RecyclerView.Adapter<Article> {
private List<Article> mData;
private ArticleViewHolder.OnSelectedListener mOnSelectedListener;
private ArticleViewHolder.OnSaveListener mOnSaveListener;
public ArticleAdapter(ArticleViewHolder.OnSelectedListener onSelectedListener, ArticleViewHolder.OnSaveListener onSaveListener) {
mOnSelectedListener = onSelectedListener;
mOnSaveListener = onSaveListener;
mData = new ArrayList<>();
}
public void replaceData(final List<Article> data) {
final List<Article> oldData = new ArrayList<>(mData);
mData.clear();
if (data != null) {
mData.addAll(data);
}
DiffUtil.calculateDiff(new DiffUtil.Callback() {
#Override
public int getOldListSize() {
return oldData.size();
}
#Override
public int getNewListSize() {
return mData.size();
}
#Override
public int areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldData.get(oldItemPosition).equals(mData.get(newItemPosition));
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldData.get(oldItemPosition).equals(mData.get(newItemPosition));
}
}).dispatchUpdatesTo(this);
}
#Override
public ArticleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_card_view, parent, false);
return new SelectLocationViewHolder(view, mOnSelectedListener, mOnSaveListener);
}
#Override
public void onBindViewHolder(ArticleViewHolder holder, int position) {
holder.bind(mData.get(position));
}
#Override
public int getItemCount() {
return mData.size();
}
}
public class ArticleViewHolder extends RecyclerView.ViewHolder {
public interface OnSelectedListener {
void onSelected(Article article);
}
public interface OnSaveListener {
void onSave(Article article);
}
private View mView;
private Article mArticle;
private OnSelectedListener mOnSelectedListener;
private OnSaveListener mOnSaveListener;
private ImageView mImageView;
private TextView mTitleTextView, mDescriptionTextView;
private FloatingActionButton mSaveButton;
public ArticleViewHolder(View itemView, final OnSelectedListener onSelectedListener, final OnSaveListener onSaveListener) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.photoImageView);
mTitleTextView = (TextView) itemView.findViewById(R.id.titleWithoutImage);
mDescriptionTextView = (TextView) itemView.findViewById(R.id.descriptionTextView);
mSaveButton = (FloatingActionButton) itemView.findViewById(R.id.floatingActionButton);
mView = itemView;
mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onSelectedListener.onSelected(mArticle);
}
});
mSaveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onSaveListener.onSave(mArticle);
}
});
}
public void bind(Article article) {
mArticle = article;
mTitleTextView.setText(article.getTitle());
mDescriptionTextView.setText(article.getDescription());
if(TextUtils.isEmpty(article.getDescription())) {
mDescriptionTextView.setVisibility(View.GONE);
}
Glide.with(mView.getContext()).load(article.getImage()).into(mImageView);
}
}
Edit
The actual issue is that your loader uses the same ArrayList every time, and keeps adding the new results to it.
public class NewsLoader extends AsyncTaskLoader<List<Article>> {
private final String[] mUrls;
private final OkHttpClient mClient;
public NewsLoader(Context context, OkHttpClient client, String... urls) {
super(context);
mClient = client;
mUrls = urls;
}
#Override
public List<Article> loadInBackground() {
List<Article> articles = new ArrayList<>();
for (String url : mUrls) {
Request request = new Request.Builder().url(url).build();
try {
Response response = mClient.newCall(request).execute();
if (response.isSuccessful()) {
parseData(response.body().string(), articles);
}
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
return articles;
}
private void parseData(List<Article> articles, String data) throws JSONException {
JSONObject forecast = new JSONObject(data);
JSONArray a = forecast.getJSONArray("articles");
for (int i = 0; i < a.length(); i++) {
JSONObject o = a.getJSONObject(i);
Article article = new Article(
o.getString("title"),
o.getString("description"),
o.getString("url"),
o.getString("urlToImage"));
articles.add(article);
}
}
}
Also, you may have noticed, I made a small change to your Article constructor. You should consider making the Article class immutable, as this will prevent you from making mistakes when dealing with multithreading. It should look something like this:
public class Article {
private final String mTitle;
private final String mDescription;
private final String mUrl;
private final String mImageUrl;
public Article(String title, String description, String url, String imageUrl) {
mTitle = title;
mDescription = description;
mUrl = url;
mImageUrl = imageUrl;
}
public String title() {
return mTitle;
}
public String description() {
return mDescription;
}
public String url() {
return mUrl;
}
public String imageUrl() {
return mImageUrl;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Article other = (Article) o;
return mTitle != null && mTitle.equals(other.mTitle) &&
mDescription != null && mDescription.equals(other.mDescription) &&
mUrl != null && mUrl.equals(other.mUrl) &&
mImageUrl != null && mImageUrl.equals(other.mImageUrl);
}
#Override
public int hashCode() {
int result = mTitle != null ? mTitle.hashCode() : 0;
result = 31 * result + (mDescription != null ? mDescription.hashCode() : 0);
result = 31 * result + (mUrl != null ? mUrl.hashCode() : 0);
result = 31 * result + (mImageUrl != null ? mImageUrl.hashCode() : 0);
return result;
}
}
#Override
public void onBindViewHolder(ArticleViewHolder holder, int position) {
holder.bindArticle(mArticlesList.get(position));
setAnimation(holder.itemView, position);
}
public void addAll(ArrayList<Articles> articles) {
mArticlesList.clear();
mArticlesList.addAll(articles);
notifyDataSetChanged();
}
If this doesn't wrok then I think your api is giving you redundant data.
Why you are using articleViewHolder.setIsRecyclable(false);
One another place which might cause the problem is
private void getMultipleUrls(String jsonData) throws JSONException {
if (mArticlesArrayList == null) {
mArticlesArrayList = getArticleForecast(jsonData);
} else {
mArticlesArrayList.addAll(getArticleForecast(jsonData));
}
}
You are calling it from a loop add adding data to your arraylist. There somehow multiple data can be inserted in your ArrayList
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I want display Review text and its Rating in another activity.
Here is my AddReview class
public class AddReview extends AppCompatActivity implements ServerRequests.AddReviewreponse {
private Button submit;
EditText addReview;
RatingBar ratingBar;
Toolbar toolbar;
ServerRequests serverRequests;
JSONParser jsonParser;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_review);
jsonParser = new JSONParser();
serverRequests = new ServerRequests(getApplicationContext());
serverRequests.setAddReviewreponse(this);
addReview=(EditText)findViewById(R.id.reviewBox);
ratingBar=(RatingBar) findViewById(R.id.ratingBar);
submit=(Button)findViewById(R.id.submit);
toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar_top);
setSupportActionBar(toolbar);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("Add Review");
// toolbar.setNavigationIcon(R.drawable.back_30);
/* toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});*/
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
String ReviewTxt = addReview.getText().toString();
float rating = ratingBar.getRating();
JSONObject obj = jsonParser.makeAddReviewJson(1,1,ReviewTxt,rating);
Log.e("final Json", obj.toString());
serverRequests.addReview(obj);
} catch (Exception e) {
}
/* Reviews.displayName.setText(RegisterActivity.name.getText().toString());
Reviews.displayReview.setText("Your Review : "+addReview.getText().toString());
Reviews.displayStars.setRating(ratingBar.getRating());*/
/* Reviews.displayStars.setText("Your Rating : " + ratingBar.getRating());
String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());
Reviews.displayDate.setText(currentDateTimeString);*/
AlertDialog alertDialog = new AlertDialog.Builder(AddReview.this).create();
alertDialog.setTitle("Review Submitted!");
alertDialog.setMessage("Thanks for your valueable review!");
alertDialog.setIcon(R.drawable.star_48);
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Write your code here to execute after dialog closed
Toast.makeText(getApplicationContext(), "You clicked on OK", Toast.LENGTH_SHORT).show();
// startActivity(new Intent(getApplicationContext(), Reviews.class));
}
});
// Showing Alert Message
alertDialog.show();
}
});
}
#Override
public void onAddReviewReposne(JSONObject object) {
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId()==android.R.id.home)
{
finish();
}
return super.onOptionsItemSelected(item);
}
}
This is the Review class where I want to display the review and its ratings
public class Reviews extends AppCompatActivity implements ServerRequests.GetReviewResponse {
public static TextView displayReview, displayDate, displayName;
public static RatingBar displayStars;
Button addReviewBtn;
android.support.v7.widget.Toolbar toolbar;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private static String LOG_TAG = "CardViewActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reviews);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view1);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
// mAdapter = new ReviewAdapter(getDataSet(jsonObject));
mRecyclerView.setAdapter(mAdapter);
toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar_top1);
setSupportActionBar(toolbar);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("Reviews");
/*displayReview = (TextView) findViewById(R.id.review);
displayStars = (RatingBar) findViewById(R.id.rating);
displayDate = (TextView)findViewById(R.id.displayDate);
displayName = (TextView)findViewById(R.id.displayName);*/
addReviewBtn = (Button)findViewById(R.id.addReviewBtn);
addReviewBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getApplicationContext(), AddReview.class));
}
});
ServerRequests serverRequests=new ServerRequests(getApplicationContext());
serverRequests.setReviewResponse(this);
serverRequests.getReviews("one");
}
private ArrayList<Review> getDataSet(JSONArray array) {
ArrayList results = new ArrayList<Review>();
for (int i = 0; i < array.length(); i++) {
try {
JSONObject object = array.getJSONObject(i);
Review obj = new Review(object.getInt("reviewId"),object.getInt("userId"),object.getString("Name"),object.getString("Review"),object.getLong("rating"));
results.add(i,obj);
}
catch (Exception e){
e.printStackTrace();
}
}
return results;
}
#Override
public void onGetReviewResponse(JSONArray jsonObject) {
mAdapter = new ReviewAdapter(getDataSet(jsonObject));
mRecyclerView.setAdapter(mAdapter);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId()==android.R.id.home)
{
finish();
}
return super.onOptionsItemSelected(item);
}
}
This is the ReviewAdapter
public class ReviewAdapter extends RecyclerView.Adapter<ReviewAdapter.DataObjectHolder> {
private static String LOG_TAG = "MyRecyclerViewAdapter";
private ArrayList<Review> mDataset;
private static MyClickListener myClickListener;
public static class DataObjectHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public static TextView name,review;
public static RatingBar rating;
public DataObjectHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.name);
review = (TextView) itemView.findViewById(R.id.review);
rating = (RatingBar) itemView.findViewById(R.id.rating);
Log.i(LOG_TAG, "Adding Listener");
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
myClickListener.onItemClick(getAdapterPosition(), v);
}
}
public void setOnItemClickListener(MyClickListener myClickListener) {
this.myClickListener = myClickListener;
}
public ReviewAdapter(ArrayList<Review> myDataset) {
mDataset = myDataset;
}
#Override
public DataObjectHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_view_review, parent, false);
DataObjectHolder dataObjectHolder = new DataObjectHolder(view);
return dataObjectHolder;
}
#Override
public void onBindViewHolder(DataObjectHolder holder, int position) {
holder.name.setText(mDataset.get(position).getName());
holder.review.setText(mDataset.get(position).getReview());
holder.rating.setRating(mDataset.get(position).getRating());
}
public void addItem(Review dataObj, int index) {
mDataset.add(index, dataObj);
notifyItemInserted(index);
}
public void deleteItem(int index) {
mDataset.remove(index);
notifyItemRemoved(index);
}
#Override
public int getItemCount() {
return mDataset.size();
}
public interface MyClickListener {
public void onItemClick(int position, View v);
}
}
This is the Pojo class of Review
public class Review {
private String name,review;
private float rating;
private int reviewId,userId;
public Review (int ReviewId, int UserId, String Name, String Review, float Rating){
reviewId = ReviewId;
userId = UserId;
name = Name;
review = Review;
rating = Rating;
}
public int getReviewId() {
return reviewId;
}
public void setReviewId(int reviewId) {
this.reviewId = reviewId;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getReview() {
return review;
}
public void setReview(String review) {
this.review = review;
}
public float getRating() {
return rating;
}
public void setRating(float rating) {
this.rating = rating;
}
}
This is the ServerRequests for add and get Review
//------------For add review------------------------------
public void setAddReviewreponse(AddReviewreponse addreviewreponse) {
this.addreviewreponse = addreviewreponse;
}
private AddReviewreponse addreviewreponse;
public interface AddReviewreponse {
void onAddReviewReposne(JSONObject object);
}
public void addReview(JSONObject jsonObject) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, Services.ADD_REVIEW, jsonObject,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
Log.e("Json response", "" + response);
boolean b = response.getBoolean("success");
if (addreviewreponse != null) {
addreviewreponse.onAddReviewReposne(response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error ", "" + error);
}
}
);
queue.add(jsonObjectRequest);
}
//------------For get review------------------------------
public void setReviewResponse(GetReviewResponse reviewResponse) {
this.getReviewResponse = reviewResponse;
}
public GetReviewResponse getReviewResponse;
public interface GetReviewResponse {
void onGetReviewResponse(JSONArray jsonObject);
}
public void getReviews(final String id) {
StringRequest request = new StringRequest(Request.Method.GET, Services.GET_REVIEW,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray array = new JSONArray(response);
Log.e("Server response", response);
if (array.length() > 0) {
if (getReviewResponse != null) {
getReviewResponse.onGetReviewResponse(array);
}
} else {
Log.e("Error is occured", "asd");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//send error repsonse back to user
Log.e("Error: ", error.getMessage());
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String, String> params = new HashMap<>();
params.put("courseId", id);
return params;
}
};
queue.add(request);
}
This is JSONParser class for AddReview
//--------For Add review---------------------------------
public JSONObject makeAddReviewJson(int studentID, int courseID, String reviewTxt, float rating) throws JSONException {
JSONObject object = new JSONObject();
object.put("studentId", studentID);
object.put("courseId", courseID);
object.put("review", reviewTxt);
object.put("ratings", rating);
return object;
}
This is the JSON response I am getting after posting the Review
E/final Json: {"studentId":1,"courseId":1,"review":"Hellooooo","ratings":3}
E/Json response: {"success":true,"msg":"Your review has been added successfully","data":{"reviewsId":18}}
private ArrayList<Review> getDataSet(JSONArray array) {
ArrayList results = new ArrayList<Review>();
for (int i = 0; i < array.length(); i++) {
try {
JSONObject object = array.getJSONObject(i);
Review obj = new Review(object.getInt("studentId"),object.getInt("courseId"),object.getString("Review"),object.getLong("rating"));
results.add(i,obj);
}
catch (Exception e){
e.printStackTrace();
}
}
return results;
}
try to change your getDataSet function with above code and check with debug point if you get any problem in some line. feel free to ask further will help you
EDIT:
You need to change your Pojo class of Review also. Because in JSON response you are not getting userId and reviewId. Hope you understand