why RecycleView items is not displayed? - android

I have a problem. When I use newsPojo at first - all displayed ok (but swipe to refresh is not work, when I use postAdapter.notifyDataSetChanged() - my items is not displayed. How can I fix it?
This is my Activity class
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private NewsApi newsApi;
private NewsPojo fromRetrofit;
private MainAdapter postAdapter;
#BindView(R.id.activity_main_swipe_to_refresh) SwipeRefreshLayout swipeRefreshLayout;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
fromRetrofit = new NewsPojo();
fromRetrofit.setArticles(new ArrayList<Article>());
response();
initRecycleView();
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
response();
swipeRefreshLayout.setRefreshing(false);
}
});
}
private void response() {
newsApi = RitApplication.getApi();
newsApi.getData().enqueue(new Callback<NewsPojo>() {
#Override
public void onResponse(Call<NewsPojo> call, Response<NewsPojo> response) {
fromRetrofit.getArticles().clear();
fromRetrofit = response.body();
postAdapter.notifyDataSetChanged();
}
}
#Override
public void onFailure(Call<NewsPojo> call, Throwable t) {
}
});
}
public void initRecycleView() {
recyclerView = findViewById(R.id.activity_main_recycle_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
postAdapter = new MainAdapter(fromRetrofit, new OnIteamClickListener() {
#Override
public void onItemClick(View itemView) {
}
}, getApplicationContext());
recyclerView.setAdapter(postAdapter);
}
}
Here you can see my Adapter class
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {
private NewsPojo newsPojo;
private OnIteamClickListener listener;
private Context mContext;
public MainAdapter(NewsPojo newsPojo, OnIteamClickListener listener, Context mContext) {
this.newsPojo = newsPojo;
this.listener = listener;
this.mContext = mContext;
}
public void clear(){
newsPojo.getArticles().clear();
notifyDataSetChanged();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_news, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(newsPojo.getArticles().get(position));
}
#Override
public int getItemCount() {
if (newsPojo != null) {
return newsPojo.getArticles().size();
} else {
return 0;
}
}
Why postAdapter.notifyDataSetChanged(); is not working?

I suggest the following:
Change the following lines:
fromRetrofit.getArticles().clear();
fromRetrofit = response.body();
postAdapter.notifyDataSetChanged();
For this:
postAdapter.cleanAddArticles(response.body());
and in the adapter add the following:
public void cleanAddArticles(NewsPojo newsPj){
this.newsPojo.getArticles().clear();
this.newsPojo.getArticles().addAll(newsPj.getArticles());
notifyDataSetChanged();
}
Note: Error depending on the circumstances must be going through object references.

When you get new values by calling response() method, then you must call initRecycleView() to set the new values to the adapter, then use notifyDataSetChanged()
#Override
public void onResponse(Call<NewsPojo> call, Response<NewsPojo> response) {
fromRetrofit.getArticles().clear();
fromRetrofit = response.body();
initRecycleView() //*** Add this.
postAdapter.notifyDataSetChanged();
}
}

first of check when you swipe refresh that time your postAdapter not getting null other wise your code is ok.
if you want to make one separate method for adapter like below..
private void setAdater(){
if (postAdapter==null) {
postAdapter = new MainAdapter(fromRetrofit, new OnIteamClickListener() {
#Override
public void onItemClick(View itemView) {
}
}, getApplicationContext());
recyclerView.setAdapter(postAdapter);
}
else{
postAdapter.notifyDataSetChanged();
}
}
and also check your from fromRetrofit object what value have. i think adapter not getting any value bacause only clear article but object has some value there for i think you make object null when getting data...
fromRetrofit=null;
fromRetrofit = response.body();

Related

Why adnroidx recycler-view click not working when click it's item?

I'm trying to implement RecyclerView onclick listener, but it is not working. I've tried a lot, and try to implement other way too, but not working at all.
My Main Class:
public class MainMenuDashboard extends AppCompatActivity{
private RecyclerView recyclerMenu;
private RecyclerViewMenuAdapter menuAdapter;
private Call<CategoryModel> categoryModelCall;
private TokenManager tokenManagerMainMenu;
private ApiService serviceMainMenu;
List<CategoryModel.Subset> menuList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu_dashboard);
tokenManagerMainMenu = TokenManager.getInstance(getSharedPreferences("prefs", MODE_PRIVATE));
serviceMainMenu = RetrofitBuilder.createServiceWithAuth(ApiService.class, tokenManagerMainMenu);
recyclerMenu = findViewById(R.id.recyclerMenu);
menuList = new ArrayList<>();
GridLayoutManager layoutManager = new GridLayoutManager(MainMenuDashboard.this, 2, GridLayoutManager.VERTICAL, false);
recyclerMenu.setLayoutManager(layoutManager);
menuAdapter = new RecyclerViewMenuAdapter(menuList);
recyclerMenu.setAdapter(menuAdapter);
menuAdapter.notifyDataSetChanged();
mainMenuDashBoardToolbar = findViewById(R.id.mainMenuDashBoardToolbar);
setSupportActionBar(mainMenuDashBoardToolbar);
menuContent();
}
private void menuContent() {
categoryModelCall = serviceMainMenu.menuContent(incomingRoleId, true);
categoryModelCall.enqueue(new Callback<CategoryModel>() {
#Override
public void onResponse(#NotNull Call<CategoryModel> call, #NotNull Response<CategoryModel> response) {
if (response.isSuccessful() && response.body() != null && response.code() != 400) {
//findViewById(R.id.shimmerCategory).setVisibility(View.GONE);
CategoryModel categoryModel = response.body();
menuList = categoryModel.getSubset();
menuAdapter = new RecyclerViewMenuAdapter(menuList);
recyclerMenu.setAdapter(menuAdapter);
//menuAdapter.notifyDataSetChanged();
menuAdapter.setOnItemClickListener(new RecyclerViewMenuAdapter.ClickListenerMenu() {
#Override
public void onClick(int position) {
Toast.makeText(MainMenuDashboard.this, "Position "+position+" Clicked", Toast.LENGTH_SHORT).show();
menuAdapter.notifyDataSetChanged();
}
});
menuAdapter.notifyDataSetChanged();
}else {
if (response.code() == 401) {
Intent i = new Intent(MainMenuDashboard.this, MainActivity.class);
i.putExtra("USER_SESSION", true);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
tokenManagerMainMenu.deleteToken();
startActivity(i);
finish();
}
}
}
#Override
public void onFailure(#NotNull Call<CategoryModel> call, #NotNull Throwable t) {
}
});
}
}
My Adapter:
public class RecyclerViewMenuAdapter extends RecyclerView.Adapter<RecyclerViewMenuAdapter.RecyclerViewHolder> {
private static final String TAG = "NotesRecyclerAdapter";
private List<CategoryModel.Subset> subsetsCategories;
private ClickListenerMenu mClickListener;
private Context context;
public RecyclerViewMenuAdapter(List<CategoryModel.Subset> subsetsCategories) {
this.subsetsCategories = subsetsCategories;
}
#NonNull
#Override
public RecyclerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler_main_menu_category, parent, false);
return new RecyclerViewHolder(view, mClickListener);
}
#Override
public void onBindViewHolder(#NonNull final RecyclerViewHolder viewHolder, final int position) {
String menuCategoryImage = subsetsCategories.get(position).getIcon();
Picasso.get().load(menuCategoryImage).placeholder(R.drawable.admin).into(viewHolder.menuThumb);
String menuCategoryName = subsetsCategories.get(position).getName();
viewHolder.menuName.setText(menuCategoryName);
//Item click
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
mClickListener.onClick(position);
//Toast.makeText(context, "Position "+position+" Clicked", Toast.LENGTH_SHORT).show();
notifyDataSetChanged();
}
});
}
#Override
public int getItemCount() {
return subsetsCategories.size();
}
public static class RecyclerViewHolder extends RecyclerView.ViewHolder{
ImageView menuThumb;
TextView menuName;
private ClickListenerMenu mListener;
//ClickListenerMenu clickListenerMenu;
public RecyclerViewHolder(View view, ClickListenerMenu clickListenerMenu) {
super(view);
menuThumb = view.findViewById(R.id.menuThumb);
menuName = view.findViewById(R.id.menuName);
mListener = clickListenerMenu;
}
}
public void setOnItemClickListener(ClickListenerMenu clickListener) {
mClickListener = clickListener;
}
public interface ClickListenerMenu {
void onClick(int position);
}
}
I still can't find where I did wrong!! Any insight will be very appreciated
Thank You
Add item click listener in your adapter.
#Override
public void onBindViewHolder(#NonNull RecyclerViewHolder viewHolder, int position) {
String menuCategoryImage = subsetsCategories.get(position).getIcon();
Picasso.get().load(menuCategoryImage).placeholder(R.drawable.admin).into(viewHolder.menuThumb);
String menuCategoryName = subsetsCategories.get(position).getName();
viewHolder.menuName.setText(menuCategoryName);
//Item click
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
// Do something
}
});
}
Initialise your recycler view outside and put this line menuAdapter.notifyDataSetChanged(); where you add data in your list.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu_dashboard);
tokenManagerMainMenu = TokenManager.getInstance(getSharedPreferences("prefs", MODE_PRIVATE));
serviceMainMenu = RetrofitBuilder.createServiceWithAuth(ApiService.class, tokenManagerMainMenu);
recyclerMenu = findViewById(R.id.recyclerMenu);
menuList = new List<CategoryModel.Subset>();
GridLayoutManager layoutManager = new GridLayoutManager(MainMenuDashboard.this, 2, GridLayoutManager.VERTICAL, false);
recyclerMenu.setLayoutManager(layoutManager);
menuAdapter = new RecyclerViewMenuAdapter(menuList);
recyclerMenu.setAdapter(menuAdapter);
menuAdapter.notifyDataSetChanged();
menuContent();
}
I hope this can help you!
Add these line in the onBindViewHolder() method:
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//remove this lines
//mClickListener.onClick(position);
//notifyDataSetChanged();
//add this
context.startActivity(new Intent(context,SecondActivity.class))
}
});
and in your MainMenuDashboard class, initialize your Adapter like this:
menuAdapter = new RecyclerViewMenuAdapter(this,menuList);
also change your Adapter constructor like this:
public RecyclerViewMenuAdapter(Context context,List<CategoryModel.Subset> subsetsCategories) {
this.subsetsCategories = subsetsCategories;
this.context = context;
}
```

How to fix recycler view won't attach adapter when retrieving data with retrofit

I am creating an app which can retrieve data from my own database. I'm using Retrofit to connect with my API. I'm creating a Bottom Navigation Activity so i could add some fragments to it. I'm using a Recycler View to show the list but it won't let me attach the adapter when i retrieve the data, it always shows this error in the log :
04-11 14:29:19.461 1912-1912/com.siscaproject.sisca E/RecyclerView: No adapter attached; skipping layout
Usually i use a single activity to create a list activity with a recycler view and it ran perfectly, but now that i use a fragment to do the same, it always gave me the error. Here is the fragment code :
public class SearchAssetFragment extends Fragment {
private static final String TAG = "SearchAssetFragment";
#BindView(R.id.search_view) SearchView searchView;
#BindView(R.id.swprefresh) SwipeRefreshLayout refresh;
#BindView(R.id.rv_list_asset) RecyclerView recyclerView;
#BindView(R.id.progress_bar) ProgressBar progressBar;
private MaterialDialog createDialog;
private AssetsAdapter adapter;
private ArrayList<Asset> listData = new ArrayList<>();
private UserService userService;
private OnFragmentInteractionListener mListener;
private AssetsAdapter.OnButtonClickListener listener = new AssetsAdapter.OnButtonClickListener() {
#Override
public void showDeleteDialog(int id) {
// TODO: Complete showDeleteDialog()
}
#Override
public void showEditDialog(Asset asset) {
// TODO: Complete showEditDialog()
}
};
public SearchAssetFragment() {
// Required empty public constructor
}
public static SearchAssetFragment newInstance() {
SearchAssetFragment fragment = new SearchAssetFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search_asset, container, false);
ButterKnife.bind(this, view);
userService = APIProperties.getUserService();
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// The method to retrieve the data from the DB and set the recycler view adapter
getAsset();
refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
getAsset();
}
});
return view;
}
private void showCreateDialog(){
// creating a dialog
}
private void showProgressBar(){
// showing a progress bar
}
private void hideProgressBar(){
// hiding a progress bar
}
// The method to retrieve the data from the DB and set the recycler view adapter
private void getAsset(){
showProgressBar();
Call<ResponseIndex<Asset>> call = userService.indexFixed(Header.auth, Header.accept);
call.enqueue(new Callback<ResponseIndex<Asset>>() {
#Override
public void onResponse(Call<ResponseIndex<Asset>> call, Response<ResponseIndex<Asset>> response) {
if(response.isSuccessful()){
int total = response.body().getTotal();
Log.i(TAG, "onResponse: total " + total);
// Initializing the adapter and set it to the recycler view
ArrayList<Asset> rows = response.body().getRows();
adapter = new AssetsAdapter(rows, getActivity(), userService, listener);
recyclerView.setAdapter(adapter);
}
else{
Log.i(TAG, "onResponse: else");
}
hideProgressBar();
refresh.setRefreshing(false);
}
#Override
public void onFailure(Call<ResponseIndex<Asset>> call, Throwable t) {
Log.e(TAG, "onFailure: " + t.getMessage() );
}
});
}
}
I'm not sure what i did wrong nor how to fix it, any answer would be appreciated. Thank you.
--Edit-- AssetsAdapter class :
public class AssetsAdapter extends RecyclerView.Adapter<AssetsAdapter.ItemHolder> implements Filterable{
private static final String TAG = "AssetsAdapter";
private OnButtonClickListener listener;
private ArrayList<Asset> listData;
private ArrayList<Asset> listDataFull;
private Context activityContext;
private UserService userService;
private MaterialDialog dialog;
public AssetsAdapter(ArrayList<Asset> listData, Context activityContext, UserService userService, OnButtonClickListener listener) {
this.listData = listData;
listDataFull = new ArrayList<>(listData);
this.activityContext = activityContext;
this.userService = userService;
this.listener = listener;
}
public AssetsAdapter(Context activityContext) {
this.activityContext = activityContext;
}
public void setListData(ArrayList<Asset> listData) {
this.listData = listData;
notifyDataSetChanged();
}
#NonNull
#Override
public ItemHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_item_assets, parent, false);
return new ItemHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ItemHolder holder, final int position) {
// holder.iv_asset.setImageDrawable(); On progress
holder.tv_name.setText(listData.get(position).getName());
holder.tv_manufacturer.setText(listData.get(position).getAsset_id());
holder.tv_quantity.setText(listData.get(position).getPurchase_cost());
//holder.tv_status.setText(listData.get(position).getModel_no()); // Still on Progress
holder.btn_delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listener.showDeleteDialog(listData.get(position).getId());
}
});
holder.btn_edit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Toast.makeText(activityContext, "Edit", Toast.LENGTH_SHORT).show();
listener.showEditDialog(listData.get(position));
}
});
}
#Override
public int getItemCount() {
if(listData.isEmpty()) return 0;
else return listData.size();
}
#Override
public Filter getFilter() {
return dataFilter;
}
private Filter dataFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
ArrayList<Asset> filteredList = new ArrayList<>();
if(charSequence == null || charSequence.length() == 0){
filteredList.addAll(listDataFull);
}
else{
String filterPattern = charSequence.toString().toLowerCase().trim();
for(Asset item : listDataFull){
if(item.getName().toLowerCase().contains(filterPattern)){
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
listData.clear();
listData.addAll((List) filterResults.values);
notifyDataSetChanged();
}
};
public class ItemHolder extends RecyclerView.ViewHolder{
private ImageView iv_asset;
private TextView tv_name;
private TextView tv_manufacturer;
private TextView tv_quantity;
private TextView tv_status;
private ImageButton btn_edit;
private ImageButton btn_delete;
public ItemHolder(View itemView) {
super(itemView);
iv_asset = itemView.findViewById(R.id.iv_asset);
tv_name = itemView.findViewById(R.id.tv_name);
tv_manufacturer = itemView.findViewById(R.id.tv_manufacturer);
tv_quantity = itemView.findViewById(R.id.tv_quantity);
tv_status = itemView.findViewById(R.id.tv_status);
btn_edit = itemView.findViewById(R.id.btn_edit);
btn_delete = itemView.findViewById(R.id.btn_delete);
}
}
public interface OnButtonClickListener {
void showDeleteDialog(final int id);
void showEditDialog(Asset asset);
}
}
First, initialize the model class and the adapter and attach to recyclerview and than get the data after retrieving data put notifydatasetchanged() or notifydatainserted() method, I think it should work,
please initialize adapter in fragment oncreateview method and set adapter to recycleview
adapter = new AssetsAdapter(rows, getActivity(), userService, listener);
recyclerView.setAdapter(adapter);
recyclerView.setAdapter(adapter);
after get response from api you can update adapter. please refer
this question

How to render render JSON data using retrofit and recylerview in android studio

I am trying use retrofit and recyclerview to display from a web app. I have the following models:
Main Activities
public class ProfileActivity extends AppCompatActivity {
private SalesAdapter mAdapter;
private RecyclerView mRecyclerView;
private SaleService mService;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView(R.layout.activity_profile );
mService = ApiUtils.getSaleService();
mRecyclerView = (RecyclerView) findViewById(R.id.rvItems);
mAdapter = new SalesAdapter(this, new ArrayList<Sale>(0), new SalesAdapter.ItemListener() {
#Override
public void onPostClick(long id) {
}
});
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setHasFixedSize(true);
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(itemDecoration);
loadAnswers();
}
public void loadAnswers() {
mService.getSales().enqueue(new Callback<List<Sale>>() {
#Override
public void onResponse(Call<List<Sale>> call, Response<List<Sale>> response) {
if(response.isSuccessful()) {
mAdapter.UpdateSales(response.body());
} else {
int statuscode = response.code();
}
}
#Override
public void onFailure(Call<List<Sale>> call, Throwable t) {
}
});
}
}
Recyclerview Adapter
public class SalesAdapter extends RecyclerView.Adapter<SalesAdapter.ViewHolder>{
private Context mContext;
private List<Sale> mSales;
private ItemListener mItemListener;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView tvLocaleName;
ItemListener mItemListener;
public ViewHolder(View itemView, ItemListener itemListener) {
super(itemView);
tvLocaleName = (TextView) itemView.findViewById(android.R.id.text1);
this.mItemListener = itemListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
Sale sale = getSales(getAdapterPosition());
this.mItemListener.onPostClick(sale.getId());
notifyDataSetChanged();
}
}
public SalesAdapter(Context mContext, List<Sale> mSales, ItemListener mItemListener) {
this.mContext = mContext;
this.mSales = mSales;
this.mItemListener = mItemListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
return new ViewHolder(view, this.mItemListener);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Sale sale = mSales.get(position);
TextView textView = holder.tvLocaleName;
textView.setText(sale.getLocaleName());
}
#Override
public int getItemCount() {
return mSales.size();
}
public void UpdateSales(List<Sale> sales) {
mSales = sales;
}
private Sale getSales(int position) {
return mSales.get(position);
}
public interface ItemListener {
void onPostClick(long id);
}
}
from the image you can see that i am able to get back the data, but how do I display in it the recyclerview? where am i going wrong with code?
Add a notifyDataSetChanged() call to your adapter after you refresh the list.
Your method should look like:
public void UpdateSales(List<Sale> sales) {
mSales = sales;
notifyDataSetChanged();
}
Check out this link to learn more about this method.

how parse JSON and set into in control. ListView or RecyclerView and click on that item can start another activity in android?

how parse JSON and set into in control. ListView or RecyclerView and click on that item can start another activity in android?
http://beta.json-generator.com/api/json/get/VJ9snXcFG
Supose we print all titles in list view using json (beta.json-generator.com/api/json/get/VJ9snXcFG).Next first title will be click open first url in json(beta.json-generator.com/api/json/get/VJ9snXcFG) ,second title will be click open second url on json (beta.json-generator.com/api/json/get/VJ9snXcFG) and so on
To parse JSON use retrofit. Here is a great example: https://square.github.io/retrofit/
To the RecyclerView add an onClicklistener in the onBindViewHolder function and start your activity there.
Example:
Json has data like this:
[{"id":302,"latitude":-23.725,"longitude":34.2773,"place":"Panda Mozambik null"},{"id":312,"latitude":46.7681,"longitude":20.8186,"place":"Kondoros Magyarország null"},{"id":322,"latitude":8,"longitude":3,"place":"rr"}]
Data class:
public class Data {
public int id;
public String place;
public float longitude;
public float latitude;
public Data(){}
}
NetAPI
public interface NetApi {
#GET("/")
Call<List<Data>> getData();
}
in Activity:
private Retrofit retrofit;
private NetApi netApi;
private RecyclerView recyclerView;
ItemAdapter adapter;
public List<Data> items = new ArrayList<Data>();
private static final String ENDPOINT_ADDRESS = "https://endpoint.com/";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
retrofit = new Retrofit.Builder().baseUrl(ENDPOINT_ADDRESS).client(new OkHttpClient.Builder().build()).addConverterFactory(GsonConverterFactory.create()).build();
netApi = retrofit.create(NetApi.class);
initRecycleView()
getData();
}
public void getData() {
netApi.getData().enqueue(new Callback<List<Data>>() {
#Override
public void onResponse(Call<List<Data>> call, Response<List<Data>> response) {
if (response.isSuccessful()) {
Log.d(TAG, response.body().toString());
items = new ArrayList<Data>((response.body()));
adapter.update(items);
} else {
Toast.makeText(MainActivity.this, "Error: " + response.message(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<List<Data>> call, Throwable t) {
}
});
}
private void initRecycleView() {
recyclerView = (RecyclerView) view.findViewById(R.id.MainRecyclerView);
adapter = new ItemAdapter();
recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
recyclerView.setAdapter(adapter);
}
ItemAdapter something like this:
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemViewHolder> {
public final List<Data> items;
public ItemAdapter() {
items = new ArrayList<>();
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView =
LayoutInflater.from(parent.getContext()).
inflate(R.layout.item_recyclerview, parent, false);
ItemViewHolder viewHolder = new ItemViewHolder(itemView);
return viewHolder;
}
#Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
Data item = items.get(position);
holder.longitude.setText(Float.toString(item.longitude));
holder.latitude.setText(Float.toString(item.latitude));
holder.place.setText(item.place);
holder.place.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"Clicked",Toast.LENGTH_LONG).show();
}
});
}
public void addItem(Data item) {
items.add(item);
notifyItemInserted(items.size() - 1);
}
#Override
public int getItemCount() {
return items.size();
}
public void update(List<Data> itemsrec) {
items.clear();
items.addAll(itemsrec);
notifyDataSetChanged();
}
public class ItemViewHolder extends RecyclerView.ViewHolder {
TextView place;
TextView longitude;
TextView latitude;
public ItemViewHolder(View itemView) {
super(itemView);
place = (TextView) itemView.findViewById(R.id.place);
longitude = (TextView) itemView.findViewById(R.id.longitude);
latitude = (TextView) itemView.findViewById(R.id.latitude);
}
}
}

RecyclerView: No adapter attached

I know that this question has been already asked, but having checked the answers, I still can't figure out the solution. This is my adapter:
public static class StarredReposViewHolder extends RecyclerView.ViewHolder {
LinearLayout starredReposLayout;
TextView starredRepoName;
public StarredReposViewHolder(View v) {
super(v);
starredReposLayout = (LinearLayout) v.findViewById(R.id.repo_starred_item_layout);
starredRepoName = (TextView) v.findViewById(R.id.starredepoName);
}
}
public StarredReposAdapter(List<GitHubstarredRepos> repos, int rowLayout, Context context) {
this.starredRepos = repos;
this.rowLayout = rowLayout;
this.context = context;
}
#Override
public StarredReposAdapter.StarredReposViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
return new StarredReposViewHolder(view);
}
#Override
public void onBindViewHolder(StarredReposViewHolder holder, int position) {
holder.starredRepoName.setText(starredRepos.get(position).getStarredName());
}
#Override
public int getItemCount() {
return starredRepos.size();
}
And this is the method I load it in:
public void loadStarredRepos (View view){
final RecyclerView recyclerViewSt = (RecyclerView) findViewById(R.id.starred_repos_recycler_view);
recyclerViewSt.setLayoutManager(new LinearLayoutManager(this));
GitHubStarredRepoAPI apiService =
ApiClient.getClient().create(GitHubStarredRepoAPI.class);
Call<List<GitHubstarredRepos>> call = apiService.getStarredRepoName(newString);
call.enqueue(new Callback<List<GitHubstarredRepos>>() {
#Override
public void onResponse(Call<List<GitHubstarredRepos>> call, Response<List<GitHubstarredRepos>>
response) {
recyclerViewSt.setAdapter(new StarredReposAdapter(response.body(), R.layout.list_item_starred_repo,
getApplicationContext()));
}
#Override
public void onFailure(Call<List<GitHubstarredRepos>> call, Throwable t) {
// Log error here since request failed
Log.e("Repos", t.toString());
}
});
}
The body of onResponse is entered correctly. The problem cannot be that it is on defined in the onCreate, as I have anther Recycle View, on the same screen, loaded from a different method. Thank you!
PS: The response of response.body()
Well, from the practice, you should have your RecyclerView#setAdapter() in mainThread in #onCreate()
public void onCreate() {
recyclerViewSt.setAdapter(myAdapter);
}
What you need to update inside the onResponse() is the dataSet that is used to feed your Adapter.
You can extract your response.body() which returns an array of object (List repos) into a global variable in your activity. Like:
List<GitHubstarredRepos> myDatasource = new ArrayList<>();
Then use it:
myAdapter = new StarredReposAdapter(myDatasource, R.layout.list_item_starred_repo, getApplicationContext()));
Next, inside the callback of network call:
onResponse(response) {
myDatasource.clear();
myDatasource.addAll(response.body());
myRecyclerview.notifyDatasetChanged();
}
Voila, my psedocode code, not sure about the syntax ;)

Categories

Resources