I'm not familiar with rx java. Trying to use it with recycleview. For some reason my code is not working Here is my code.
Fragment with recycle view
public class CheeseListFragment extends Fragment {
private final CompositeSubscription subscriptions = new CompositeSubscription();
private PublishSubject<String> timespanSubject;
private final Func1<String, Observable<LiveInfo>> trendingSearch =
new Func1<String, Observable<LiveInfo>>() {
#Override
public Observable<LiveInfo> call(String s) {
RadioLiveInfoObservableService radioLiveInfoObservableService=ApiProvider.getInstance().getRadioObserverInfo();
return radioLiveInfoObservableService.radioInfo(Type.INTERVAL)
.observeOn(AndroidSchedulers.mainThread())
.doOnError(trendingError)
.onErrorResumeNext(Observable.<LiveInfo>empty());
}
};
private final Action1<Throwable> trendingError = new Action1<Throwable>() {
#Override public void call(Throwable throwable) {
Timber.e(throwable, "Failed to get trending repositories");
}
};
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
timespanSubject = PublishSubject.create();
final RecyclerView rv = (RecyclerView) inflater.inflate(
R.layout.fragment_cheese_list, container, false);
setupRecyclerView(rv);
subscriptions.add(timespanSubject
.flatMap(trendingSearch)
.map(SearchResultToRepositoryList.instance())
.subscribe(adapter));
return rv;
}
private SimpleStringRecyclerViewAdapter adapter;
private void setupRecyclerView(RecyclerView recyclerView) {
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
adapter=new SimpleStringRecyclerViewAdapter(getActivity(), new SimpleStringRecyclerViewAdapter.CurrentShowClickListener() {
#Override
public void onCurrentShowClick(Current currentShow) {
Intent intent = new Intent(CApplication.getAppContext(), CheeseDetailActivity.class);
intent.putExtra(CheeseDetailActivity.EXTRA_NAME, currentShow.getName());
CApplication.getAppContext().startActivity(intent);
}
});
recyclerView.setAdapter(adapter);
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onChanged() {
Toast.makeText(getActivity(),"data changed",Toast.LENGTH_SHORT).show();
}
});
}
private List<String> getRandomSublist(String[] array, int amount) {
ArrayList<String> list = new ArrayList<>(amount);
Random random = new Random();
while (list.size() < amount) {
list.add(array[random.nextInt(array.length)]);
}
return list;
}
public static class SimpleStringRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> implements Action1<List<Current>> {
private List<Current> currentShows = Collections.emptyList();
public interface CurrentShowClickListener {
void onCurrentShowClick(Current currentShow);
}
private final CurrentShowClickListener currentShowClickListener;
private final TypedValue mTypedValue = new TypedValue();
private int mBackground;
#Override
public void call(List<Current> currentShows) {
this.currentShows = currentShows;
notifyDataSetChanged();
}
public SimpleStringRecyclerViewAdapter(Context context,CurrentShowClickListener currentShowClickListener) {
context.getTheme().resolveAttribute(R.attr.selectableItemBackground, mTypedValue, true);
mBackground = mTypedValue.resourceId;
this.currentShowClickListener = currentShowClickListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ListItemView view = (ListItemView)LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
view.setBackgroundResource(mBackground);
return new ViewHolder(view);
}
#Override public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.bindTo(currentShows.get(i));
}
#Override public long getItemId(int position) {
return position;
}
#Override public int getItemCount() {
return currentShows.size();
}
public final class ViewHolder extends RecyclerView.ViewHolder {
public final ListItemView itemView;
private Current currentShow;
public ViewHolder(ListItemView itemView) {
super(itemView);
this.itemView = itemView;
this.itemView.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
currentShowClickListener.onCurrentShowClick(currentShow);
}
});
}
public void bindTo(Current currentShow) {
this.currentShow = currentShow;
itemView.bindTo(currentShow);
}
}
}
}
SearchToResultRepositoryList
public final class SearchResultToRepositoryList implements Func1<LiveInfo, List<Current>> {
private static volatile SearchResultToRepositoryList instance;
public static SearchResultToRepositoryList instance() {
if (instance == null) {
instance = new SearchResultToRepositoryList();
}
return instance;
}
#Override public List<Current> call(LiveInfo repositoriesResponse) {
List<Current> currents=new ArrayList<>();
currents.add(repositoriesResponse.getCurrent());
return currents;
}
}
REST
public interface RadioLiveInfoObservableService {
#GET("/api/live-info/")
Observable<LiveInfo> radioInfo(
#Query("type") Type type);
}
It's just doing nothing. I tried to debug it trendingSearch.call is not called at all.
I can make it work only this way. But still i want to know how to it with subscription
RadioLiveInfoObservableService radioLiveInfoObservableService=ApiProvider.getInstance().getRadioObserverInfo();
radioLiveInfoObservableService.commits(Type.INTERVAL)
.observeOn(AndroidSchedulers.mainThread())
.doOnError(trendingError)
.onErrorResumeNext(Observable.<LiveInfo>empty()).subscribe(new Action1<LiveInfo>() {
#Override
public void call(LiveInfo liveInfo) {
List<Current> currents=new ArrayList<Current>();
currents.add(liveInfo.getCurrent());
adapter.currentShows=currents;
adapter.notifyDataSetChanged();
rv.setAdapter(adapter);
}
});
That's a lot of code to digest looking for errors, but off the top of my head nothing will happen until timeSpanSubject.onNext() is called. I don't see this called anywhere but maybe there is some missing code you are not showing.
If there is no missing code that calls timeSpanSubject.onNext(), then you could use either a BehaviorSubject which will emit an item when first subscribed to or another Observable such as timer or interval depending on what you are trying to do. timer would subscribe to your trendingSearch Observable a single time whereas using an interval would subscribe multiple times.
Related
I have implemented a basic ListAdapter in RecyclerView as I am using View Model. The data I am getting is from networkManager to Viewmodel by calling API. Even when I did got the data the submitList is not Working and thus no data is getting inflated.
UpcomingGroupFragment
public class UpcomingGroupFragment extends Fragment {
private UpcomingViewModel mViewModel;
private RecyclerView recyclerView;
private GroupAdapter_new adapter;
public static UpcomingGroupFragment newInstance() {
return new UpcomingGroupFragment();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_chatgroups, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
adapter = new GroupAdapter_new();
recyclerView.setAdapter(adapter);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(UpcomingViewModel.class);
mViewModel.getMutableLiveData().observe(this, new Observer<List<ChatGroups_New>>() {
#Override
public void onChanged(#Nullable List<ChatGroups_New> chatGroups_news) {
adapter.submitList(chatGroups_news);
Log.e("Upcoming", String.valueOf(chatGroups_news.size()));
}
});
}
}
The Adapter Class extends the ListAdapter.
Link for overriding submitlist: https://stackoverflow.com/a/50062174
The Code is as follows:
GroupAdapter_new
public class GroupAdapter_new extends ListAdapter<ChatGroups_New,GroupAdapter_new.ViewHolder> {
public GroupAdapter_new() {
super(DIFF_CALLBACK);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
int layoutID = R.layout.ongoing_group;
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(layoutID,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ChatGroups_New currentGroup = getItem(position);
holder.text_flightarrival.setText(currentGroup.getFlightNameArrival());
}
class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
//... Finding ID's for various Views
}
}
/****ADDED THIS FROM CODE*****/
#Override
public void submitList(List<ChatGroups_New> list) {
super.submitList(list != null ? new ArrayList<ChatGroups_New>() : null);
}
/***********/
private static final DiffUtil.ItemCallback<ChatGroups_New> DIFF_CALLBACK =
new DiffUtil.ItemCallback<ChatGroups_New>() {
#Override
public boolean areItemsTheSame(ChatGroups_New oldItem, ChatGroups_New newItem) {
Log.e("areItemsTheSame", String.valueOf(oldItem.getMergedLogId() == newItem.getMergedLogId()));
return oldItem.getMergedLogId() == newItem.getMergedLogId();
}
#Override
public boolean areContentsTheSame(ChatGroups_New oldItem, ChatGroups_New newItem) {
if(oldItem.getFlightIcon().equals(newItem.getFlightIcon()) && oldItem.getFlightNameArrival().equals(newItem.getFlightNameArrival())){
if(oldItem.getGateValue().equals(newItem.getGateValue()) && oldItem.getEtaValue().equals(newItem.getEtaValue())){
if(oldItem.getAlertValue().equals(newItem.getAlertValue()) && oldItem.getTaskcompletedValue().equals(newItem.getTaskcompletedValue())){
Log.e("areContentsTheSame", "true");
return true;
}
}
}
return false;
}
};
}
If you want to see my ViewModel Class then:
UpcomingViewModel
public class UpcomingViewModel extends AndroidViewModel
implements I_NetworkResponse {
private NetworkManager networkManager;
private SharedPrefService prefService;
private HashMap<String, String> header;
private final String TAG = "UpcomingViewModel";
private List<ChatGroups_New> upcomingList;
private MutableLiveData<List<ChatGroups_New>> mutableLiveData;
public UpcomingViewModel(#NonNull Application application) {
super(application);
prefService = SharedPrefService.getInstance(application);
networkManager = new NetworkManager(application,this);
upcomingList = new ArrayList<>();
mutableLiveData = new MutableLiveData<>();
mutableLiveData.setValue(upcomingList);
header = new HashMap<>();
header.put("authorizationcode",prefService.getStringValue(Keys.getPreferenceAuthKey()));
if(upcomingList.isEmpty()){
networkManager.Volley_JsonObjectRequest(Keys.getBaseUrl()+"AviLeap/flights/upcoming",
header,null,TAG,"AviLeap/flights/upcoming");
}
}
public MutableLiveData<List<ChatGroups_New>> getMutableLiveData() { return mutableLiveData; }
#Override
public void getNetworkSuccessResponse(String TAG, String successResponse, String TAGforApi) {
Log.e(TAGforApi,successResponse);
parseUpcomingFlight(successResponse, upcomingList);
mutableLiveData.setValue(upcomingList);
}
#Override
public void getNetworkFailResponse(String TAG, VolleyError failResponse, String TAGforApi) { }
#Override
protected void onCleared() {
super.onCleared();
networkManager.stopNetworkCallsWithTag(TAG);
}
private void parseUpcomingFlight(String successResponse, List<ChatGroups_New> upcomingList) {
try {
JSONObject rootObject = new JSONObject(successResponse);
if(rootObject.has("upcomingflights") && rootObject.opt("upcomingflights") instanceof JSONArray){
JSONArray flightsArray = rootObject.optJSONArray("upcomingflights");
for(int flightIndex = 0; flightIndex < flightsArray.length(); flightIndex++){
JSONObject flightObject = flightsArray.optJSONObject(flightIndex);
int mergedLogId = flightObject.optInt("logid");
upcomingList.add(new ChatGroups_New(mergedLogId));
Log.e("parseUpcomingFlight", String.valueOf(upcomingList.size()));//..... Log Point
}
}
}
catch (JSONException e) { e.printStackTrace(); }
}
}
Initially the Size of the List is zero, so the Error is coming for as
AviLeap/flights/upcoming: //.... API CALL
2019-03-02 13:25:53.652 8477-8477/com.avileapconnect.com E/parseUpcomingFlight: 1 2019-03-02 13:25:53.652 8477-8477/com.avileapconnect.com E/parseUpcomingFlight: 2
2019-03-02 13:25:53.653 8477-8477/com.avileapconnect.com E/Upcoming: 2
The above logs show that the data is being added to the arraylist, but it is not updating. Also after all these logs when I go back to my Fragment I get the following error.
no adapter Attached, Skipping Layout
One more thing to add is that the adapter's getItemCount is getting updated properly. But even after that I am getting error:
no adapter Attached, Skipping Layout
EDIT: I fixed the error by commenting out the code for overriding the SubmitList method. I am also setting the adapter in the observer method in the fragment Class
I have an issue while using staggered GridView Layout. After I delete an element from the list, the item in the staggered gridview don't properly rearrange themselves. I mean, they leave lots of empty spaces above them.
Here are some pictures of before and after deleting,
before:
after:
one more:
But after I close the app and open it again, they reorder themselves properly.
Here is my code,
Fragment:
public class TaskListFragment extends Fragment {
public static final String TAG = TaskListFragment.class.getSimpleName();
private FragmentTaskListBinding mBinding;
private TaskViewModel viewModel;
private TaskListAdapter taskListAdapter;
private List<TaskEntity> entityList;
private StaggeredGridLayoutManager layoutManager;
public TaskListFragment() {
// Required empty public constructor
}
public static TaskListFragment instantiate() {
return new TaskListFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_task_list,
container, false);
mBinding.setFabClick(clickCallback);
layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mBinding.taskListRecyclerView.setItemAnimator(new DefaultItemAnimator());
mBinding.taskListRecyclerView.setLayoutManager(layoutManager);
return mBinding.getRoot();
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
viewModel = ViewModelProviders.of(this)
.get(TaskViewModel.class);
subscribeUi(viewModel);
}
private void subscribeUi(TaskViewModel viewModel) {
viewModel.loadTasks().observe(this, taskEntities -> {
if (taskEntities != null) {
setListData(taskEntities);
}
});
mBinding.executePendingBindings();
}
private void setListData(List<TaskEntity> taskEntities) {
this.entityList = taskEntities;
taskListAdapter = new TaskListAdapter();
taskListAdapter.setTaskList(entityList);
mBinding.taskListRecyclerView.setAdapter(taskListAdapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(createHelperCallback());
itemTouchHelper.attachToRecyclerView(mBinding.taskListRecyclerView);
}
private final FabClickCallback clickCallback = new FabClickCallback() {
#Override
public void onFabClick() {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
((MainListActivity) getActivity()).start();
}
}
};
private ItemTouchHelper.SimpleCallback createHelperCallback() {
return new SwipeToDelete() {
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
viewModel.deleteTask(entityList.get(position));
entityList.remove(position);
taskListAdapter.notifyItemRemoved(position);
}
};
}
}
Adapter:
public class TaskListAdapter extends RecyclerView.Adapter<TaskListAdapter.TaskViewHolder> {
private List<? extends Task> mTasks;
public TaskListAdapter() {
}
public void setTaskList(List<? extends Task> tasks) {
if (mTasks == null) {
mTasks = tasks;
notifyItemRangeInserted(0, mTasks.size());
} else {
DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
#Override
public int getOldListSize() {
return mTasks.size();
}
#Override
public int getNewListSize() {
return tasks.size();
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return mTasks.get(oldItemPosition).getTId() ==
tasks.get(newItemPosition).getTId();
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
Task newTask = tasks.get(newItemPosition);
Task oldTask = mTasks.get(oldItemPosition);
return newTask.getTId() == oldTask.getTId()
&& Objects.equals(newTask.getTaskName(), oldTask.getTaskName())
&& Objects.equals(newTask.getTaskDescription(), oldTask.getTaskDescription());
}
});
mTasks = tasks;
result.dispatchUpdatesTo(this);
}
}
#Override
public TaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
TaskItemBinding mBinding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()), R.layout.task_item,
parent, false);
return new TaskViewHolder(mBinding);
}
#Override
public void onBindViewHolder(TaskViewHolder holder, int position) {
holder.mBinding.setTask(mTasks.get(position));
}
#Override
public int getItemCount() {
return mTasks == null ? 0 : mTasks.size();
}
static class TaskViewHolder extends RecyclerView.ViewHolder {
final private TaskItemBinding mBinding;
public TaskViewHolder(TaskItemBinding taskItemBinding) {
super(taskItemBinding.getRoot());
mBinding = taskItemBinding;
}
}
}
Edit: I found the answer to my problem.
I've been creating a new adapter over and over and setting it to the recyclerview in setListData() method instead of putting them in onCreateView method. Moving those two lines of code to onCreateView fixed my issue.
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.
I tried to set the adapter on fragment, but nothing shows up.
The object retrieves the data from API but doesn't show on the screen.
I have already put the break point on rvItem.setAdapter(mainAdapter); but nothings happen, the debug passes straight through.
public class ItemFragment extends Fragment {
private MainAdapter mainAdapter;
private ItemPresenter itemPresenter;
private GridLayoutManager mLayoutManager;
private List<ObjectAdapter> list = new ArrayList<>();
private String region = "br";
#Bind(R.id.rvItem)
RecyclerView rvItem;
public ItemFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_item, container, false);
ButterKnife.bind(this, view);
itemPresenter = new ItemPresenter();
mLayoutManager = new GridLayoutManager(getActivity(), 4);
rvItem.setLayoutManager(mLayoutManager);
getList();
return view;
}
private void getList() {
itemPresenter.loadItemList(region, "all", AppConfigs.api_key, new ItemListListener() {
#Override
public void onRequestStarted() {
}
#Override
public void onRequestFinished() {
}
#Override
public void onError(Throwable error) {
}
#Override
public void onItemListLoad(List<ItemDto> itemList) {
displayItemList(ObjectAdapter.convertItemToObjetct(itemList));
}
});
}
public void displayItemList(List<ObjectAdapter> itemList) {
list = itemList;
mainAdapter = new MainAdapter(getActivity(), list, new MainAdapter.OnObjectClickListener() {
#Override
public void OnObjectClickListener(ObjectAdapter objectAdapter) {
Toast.makeText(getActivity(), "Object Adapter" + objectAdapter.Id, Toast.LENGTH_SHORT).show();
}
});
rvItem.setAdapter(mainAdapter);
mainAdapter.notifyDataSetChanged();
}
}
Adapter:
public class MainAdapter extends
RecyclerView.Adapter<MainAdapter.MainAdapterViewHolder> {
public List<ObjectAdapter> mObjecterList;
private final OnObjectClickListener listener;
private Context mContext;
public interface OnObjectClickListener {
void OnObjectClickListener(ObjectAdapter objectAdapter);
}
public MainAdapter(Context context, List<ObjectAdapter> objectAdapterList, OnObjectClickListener listener) {
this.mObjecterList = objectAdapterList;
this.listener = listener;
this.mContext = context;
}
#Override
public MainAdapter.MainAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_main_adapter, parent, false);
return new MainAdapterViewHolder(view);
}
#Override
public void onBindViewHolder(MainAdapter.MainAdapterViewHolder holder, int position) {
ObjectAdapter ob = mObjecterList.get(position);
holder.tvNameText.setText(ob.Name);
holder.bind(mObjecterList.get(position), listener);
String url = "";
switch (ob.Type){
case CHAMPION: url = String.format(AppConfigs.portraitChampion, ob.Portrait);
break;
case SPELL: url = String.format(AppConfigs.portraitSpell, ob.Portrait);
break;
case ITEM: url = String.format(AppConfigs.portraitItem, ob.Portrait);
break;
}
Picasso.with(mContext).load(url).into(holder.ivRetrato);
}
#Override
public int getItemCount() {
return this.mObjecterList.size();
}
public static class MainAdapterViewHolder extends RecyclerView.ViewHolder {
public TextView tvNameText;
public ImageView ivRetrato;
public MainAdapterViewHolder(View itemView) {
super(itemView);
this.tvNameText = (TextView) itemView.findViewById(R.id.tvNameText);
this.ivRetrato = (ImageView) itemView.findViewById(R.id.ivImagePortrait);
}
public void bind(final ObjectAdapter objectAdapterListItem, final OnObjectClickListener listener) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.OnObjectClickListener(objectAdapterListItem);
}
});
}
}
}
You need to set adapter directly at onCreateView method and call notifyDataSetChanged() of adapter when data loaded
This is how I'm setting up my Recycler view in my Search Fragment. I don't understand why I keep getting the same error and what I'm missing.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search, container, false);
searchText = (EditText)view.findViewById(R.id.searchText);
searchButton = (Button)view.findViewById(R.id.searchButton);
nutritionRecyclerView = (RecyclerView)view.findViewById(R.id.nutritionRecyclerView);
layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
searchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ApiClient.getInstance().getNutritionApiAdapter()
.getSearchResults(
AppDefines.APPLICATION_ID,
AppDefines.APPLICATION_KEY,
searchText.getText().toString())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<SearchResultsModel>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(SearchResultsModel searchResultsModel) {
// On handling the http response, instantiate a new adapter with the results
adapter = new NutritionAdapter(searchResultsModel.getSearchResults());
adapter.setOnItemSelected(new NutritionAdapter.OnItemSelected() {
#Override
public void onSelected(NutritionItemModel item) {
if (onFragmentEvent != null) {
onFragmentEvent.onEvent(item);
}
}
});
// Assigning the LayoutManager to the RecyclerView
nutritionRecyclerView.setLayoutManager(layoutManager);
// Assigning the Adapter to the RecyclerView. If this isn't done, the view will not populate
nutritionRecyclerView.setAdapter(adapter);
}
});
}
});
return view;
}
Here is my ApiClient
public class ApiClient {
private static ApiClient instance;
public static ApiClient getInstance() {
if (instance == null) {
instance = new ApiClient();
}
return instance;
}
public NutritionApiAdapter getNutritionApiAdapter() {
NutritionApiAdapter api = new Retrofit.Builder()
.baseUrl(AppDefines.BASE_API_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build()
.create(NutritionApiAdapter.class);
return api;
}
}
And this is my NutritionApiAdapter
public interface NutritionApiAdapter {
#GET("item")
Observable<SearchResultsModel> getSearchResults(
#Query("_app_id") String appId,
#Query("_app_key") String appKey,
#Query("q") String searchString);
}
NutritionAdpater
public class NutritionAdapter extends RecyclerView.Adapter<NutritionItemViewHolder>{
private ArrayList<NutritionItemModel> nutritionItemCollection;
private OnItemSelected onItemSelected;
public NutritionAdapter(ArrayList<NutritionItemModel> nutritionItemCollection){
this.nutritionItemCollection = nutritionItemCollection;
}
#Override
public NutritionItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_nutrition, parent, false);
return new NutritionItemViewHolder(view);
}
#Override
public void onBindViewHolder(NutritionItemViewHolder holder,int position) {
NutritionItemModel item = nutritionItemCollection.get(position);
holder.setOnRecipeItemClicked(new NutritionItemViewHolder.OnNutritionItemClicked(){
#Override
public void onClick(NutritionItemModel item) {
if(onItemSelected != null) {
onItemSelected.onSelected(item);
}
}
});
// Bind the RecipeItemModel data to the view managed by the ViewHolder
holder.bind(item);
}
#Override
public final void onViewRecycled(final NutritionItemViewHolder holder) {
super.onViewRecycled(holder);
holder.setOnRecipeItemClicked(null);
holder.unbind();
}
#Override
public int getItemCount() {return nutritionItemCollection.size();}
public void setOnItemSelected(OnItemSelected onItemSelected) {
this.onItemSelected = onItemSelected;
}
public interface OnItemSelected {
void onSelected(NutritionItemModel item);
}
}
and NutritionItemViewHolder
public class NutritionItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView foodName;
private ImageView foodThumbnail;
private NutritionItemModel item;
private TextView item_name;
private TextView brand_name;
private OnNutritionItemClicked onNutritionItemClicked;
//todo add other elements here
public NutritionItemViewHolder(final View itemView) {super(itemView);}
public final void bind(final NutritionItemModel item) {
item_name = (TextView)itemView.findViewById(R.id.item_name);
brand_name = (TextView)itemView.findViewById(R.id.brand_name);
//foodThumbnail = (ImageView)itemView.findViewById(R.id.foodThumbnail);
//todo add other element id things here
/*
//used for preloading images
Glide.with(itemView.getContext())
.load(item.getSmallImageUrls().get(0))
.into(foodThumbnail);
*/
item_name.setText(item.getFields().getItem_name());
brand_name.setText(item.getFields().getBrand_name());
}
public final void unbind() {
//todo ?
//For later with butterknife
}
#Override
public void onClick(View v) {
if(onNutritionItemClicked != null) {
onNutritionItemClicked.onClick(item);
}
}
// The setter that allows other classes to create a reference to the listener.
public void setOnRecipeItemClicked(OnNutritionItemClicked onNutritionItemClicked) {
this.onNutritionItemClicked = onNutritionItemClicked;
}
// An interface is added as an internal implementation in our ViewHolder. This will allow
// classes that instantiate a new instance of this ViewHolder to subscribe to this interface
// and listen for events.
public interface OnNutritionItemClicked {
void onClick(NutritionItemModel item);
}
}
set the layoutmanager,
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
list.setLayoutManager(llm);
list.setAdapter(adapter);
Maybe this can help you.