Hy, I want to display the resuilt of SQLite.net query with my RecyclerView in my Xamarin.Android app. When excecuting the query synchronous everythin works fine. but when I excecute it async, the Recyclerview won't show up. I checked the result of the query and it contains all the expected entries.
This works:
songsEntryArray = MusicShareDatabase.Instance.Database.Table<SongsEntry>().ToArray();
mRecyclerView = rootView.FindViewById<RecyclerView>(Resource.Id.allsongs_recyclerview);
mLayoutManager = new LinearLayoutManager(this.Activity);
mRecyclerView.SetLayoutManager(mLayoutManager);
mAdapter = new AllSongsAdapter(songsEntryArray);
mAdapter.ItemClick += OnItemClick;
mRecyclerView.SetAdapter(mAdapter);
mAdapter.NotifyDataSetChanged();
And this doesn't work:
var query = MusicShareDatabase.Instance.DatabaseAsync.Table<SongsEntry>();
query.ToListAsync().ContinueWith(t =>
{
mRecyclerView = rootView.FindViewById<RecyclerView>(Resource.Id.allsongs_recyclerview);
mLayoutManager = new LinearLayoutManager(this.Activity);
mRecyclerView.SetLayoutManager(mLayoutManager);
mAdapter = new AllSongsAdapter(t.Result.ToArray());
mAdapter.ItemClick += OnItemClick;
mRecyclerView.SetAdapter(mAdapter);
mAdapter.NotifyDataSetChanged();
});
I think that ContinueWith(Action action) is running on the background thread.
You need to run this code on the UIThread with method Activity.RunOnUiThread(Action action);.
Code
query.ToListAsync().ContinueWith(t =>
{
Activity.RunOnUiThread(() => {
mRecyclerView = rootView.FindViewById<RecyclerView>(Resource.Id.allsongs_recyclerview);
mLayoutManager = new LinearLayoutManager(this.Activity);
mRecyclerView.SetLayoutManager(mLayoutManager);
mAdapter = new AllSongsAdapter(t.Result.ToArray());
mAdapter.ItemClick += OnItemClick;
mRecyclerView.SetAdapter(mAdapter);
mAdapter.NotifyDataSetChanged();
});
});
Related
I want to do a RESET button. I already successfully do for Spinner and Seekbar but failed to do for RecyclerView which is my filtering result. There is no error, but as you can see in my output interface, ONLY the recyclerView did not empty...
My coding:-
resetButton.setOnClickListener(new View.OnClickListener() {
final MediaPlayer mediaPlayer = MediaPlayer.create(FilterTuitionCentre.this, R.raw.soundeffect1);
#Override
public void onClick(View v) {
mediaPlayer.start();
spLocation.setSelection(0);
seekbarPrice.setProgress(0);
spAcademicLevel.setSelection(0);
spSubject.setSelection(0);
recyclerView.invalidate();
}
});
My interface output:-
My adapter coding:-
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(mAdapter);
I assume that you have following initialization for your recyclerView :
YourAdapter adapter = new YourAdapter(items);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
To clear items(Empty) RecyclerView you need to :
items.clear();
adapter.notifyDataSetChanged();
We have a traditional ListView interfaced with a RecyclerView Adapter and a Model class. When we log in to Firebase we navigate to the ListView nothing is loaded in the ListView. We then go back to the login activity and repeat the process
Then all the data is loaded from a very simple DB child node Table List
We tired the Firebase RecyclerAdapter with no luck we may have had the wrong UI or version. Our question is why do we need to make two trips to the list view to load the data? We will post the ListView code NO Errors are generated We did try placing the code in an OnStart method no luck with that
db = FirebaseDatabase.getInstance().getReference();
dbRef = db.child("Table List");
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren())
listArrayList.add(child.getValue(String.class));
sz = listArrayList.size();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
sz = listArrayList.size();
if(sz == 0){
tvNoData.setVisibility(View.VISIBLE);
tvNoData.setText("No Quiz's Found\n\nClick On Make New Quiz");
mRecyclerView = findViewById(R.id.recycleview);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new TableTrackerAdapter(this,listArrayList);
mRecyclerView.setAdapter(mAdapter);
}
if(sz > 0){
tvNoData.setVisibility(View.INVISIBLE);
mRecyclerView = findViewById(R.id.recycleview);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new TableTrackerAdapter(this,listArrayList);
mRecyclerView.setAdapter(mAdapter);
}
The reason for that is because Firebase database is asynchronous, in other words the recyclerview is getting populated with an empty arraylist before firebase is finished loading data, I faced similar problem before.
Just move everything that depends on your arraylist inside firebase datachange, and the problem will be fixed like this.
public void setupRecyclerView(){
if(sz == 0){
tvNoData.setVisibility(View.VISIBLE);
tvNoData.setText("No Quiz's Found\n\nClick On Make New Quiz");
mRecyclerView = findViewById(R.id.recycleview);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(MainActivity.this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new TableTrackerAdapter(MainActivity.this,listArrayList);
mRecyclerView.setAdapter(mAdapter);
}
if(sz > 0){
tvNoData.setVisibility(View.INVISIBLE);
mRecyclerView = findViewById(R.id.recycleview);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(MainActivity.this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new TableTrackerAdapter(MainActivity.this,listArrayList);
mRecyclerView.setAdapter(mAdapter);
}
}
db = FirebaseDatabase.getInstance().getReference();
dbRef = db.child("Table List");
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot != null){
for (DataSnapshot child : dataSnapshot.getChildren()){
listArrayList.add(child.getValue(String.class));
}
sz = listArrayList.size();
setupRecyclerView();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I am using a Staggered Grid Layout to show data to recycler view from database.I have faced a problem where after deleting an item from db as well as remove position from adapter, I got some item rendering issues.Like the scattered all over the place.
Here is my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note_favorite);
ButterKnife.bind(this);
toolbar = (Toolbar) findViewById(R.id.fav_note_toolbar);
setSupportActionBar(toolbar);
noteAdapter = new NoteAdapter(noteModelList, NoteFavoriteActivity.this);
layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(noteAdapter);
touchListenerRecycler();
loadDataAll();
}
private void loadAll() {
noteModelList.clear();
DBManagerFav dbManagerFav = DBManagerFav.getInstance(NoteFavoriteActivity.this);
dbManagerFav.openDataBase();
noteModelList = dbManagerFav.getAllNoteList();
Log.i(TAG, " size : " + noteModelList.size());
noteAdapter = new NoteAdapter(noteModelList, NoteFavoriteActivity.this);
recyclerView.setAdapter(noteAdapter);
noteAdapter.notifyDataSetChanged();
dbManagerFav.closeDataBase();
}
private void deleteOperation() {
DBManagerFav dbManagerFav = DBManagerFav.getInstance(NoteFavoriteActivity.this);
dbManagerFav.openDataBase();
NoteModel noteModel = new NoteModel();
noteModel.setId(noteModelList.get(adapterClickedPosition).getId());
int status = dbManagerFav.deleteNote(noteModelList.get(adapterClickedPosition).getId());
if (status > 0) {
noteAdapter.removeAt(adapterClickedPosition);
}
dbManagerFav.closeDataBase();
loadDataAll();
}
//this belongs to adapter
public void removeAt(int position) {
Log.d(TAG, " removing at position : " + position);
noteModelList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, noteModelList.size());
notifyDataSetChanged();
}
I have attached two screenshots before and after
Before deleting an item
after deleting an item
Can you point me out what else do I need ?
You can put inside loadDataAll(){
layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
//........
}
Voila..
I have a RecyclerView with a LinearLayoutManager that is backed by an adapter with items of different height. Is there a way to tell the RecyclerView to set the scroll position so that item X appears (more or less) exactly at the bottom of the screen?
I tried LinearLayoutManager.scrollToPosition() but this will position the item at the top of the view.
MyAdapter mAdapter;
RecyclerView recyclerView;
List<ItemData> data = new ArrayList<>();
LinearLayoutManager llm = new LinearLayoutManager(this);
try this in OnCreate method
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(llm);
llm.setStackFromEnd(true);
mAdapter = new MyAdapter(data, getApplication());
recyclerView.setAdapter(mAdapter);
and when you insert an item try this
mAdapter.notifyItemInserted(data.size() - 1);
llm.scrollToPosition(data.size() - 1);
Try this in mainActivity.class
rv_journey.setAdapter(ca);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
scrollList();
}
}, 500);
Here is my scroll Method
private void scrollList(){
rv_journey.post(new Runnable() {
#Override
public void run() {
// Call smooth scroll
rv_journey.smoothScrollToPosition(Index);
}
});
}
Set index from Adapter class which extend RecyclerView.Adapter Where You need to scroll...
if (Condition) {
mainActivity.Index=position+1;
}
}
Happy Coding...
Am I using RecyclerView correctly? Whenever I update the data, the is one moment in which the view still displays the old data, despite having modified the dataset and having called the relevant notify method. On top of that, I don't see any animations, so I must be doing something wrong.
Here is the relevant snippet of code:
private void refreshData() {
Utils.hideSoftKeyboard(this);
if (!Utils.isOnline(getApplicationContext())) {
Toast.makeText(getApplicationContext(), R.string.toast_no_conn, Toast.LENGTH_SHORT).show();
return;
}
String stopNumber = mStopEdit.getText().toString();
if (stopNumber.isEmpty()) {
Toast.makeText(getApplicationContext(), R.string.toast_no_stop, Toast.LENGTH_SHORT).show();
return;
}
mResultNoStop.setVisibility(View.GONE);
mResults.setVisibility(View.GONE);
mProgressCircle.setVisibility(View.VISIBLE);
if (!mDataset.isEmpty()) {
int size = mDataset.size();
mDataset.clear();
mAdapter.notifyItemRangeRemoved(0, size);
}
FiveT.getStopData(stopNumber, mRequestQueue, new FiveT.StopDataClientListener() {
#Override
public void onResponse(ApiResult result) {
mProgressCircle.setVisibility(View.GONE);
if (result.getStopResults().size() == 0) {
mResultNoStop.setVisibility(View.VISIBLE);
Toast.makeText(getApplicationContext(), R.string.toast_no_data, Toast.LENGTH_SHORT).show();
return;
}
int i = 0;
mStopName.setText(result.getStopName());
for (StopResult res : result.getStopResults()) {
mDataset.add(res);
mAdapter.notifyItemInserted(i++);
}
mResults.setVisibility(View.VISIBLE);
}
});
}
EDIT: I initialize the RecyclerView like this:
mDataset = new ArrayList<StopResult>();
mRecyclerView = (RecyclerView) findViewById(R.id.results_recycler_view);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new RecyclerViewAdapter(mDataset, getApplicationContext());
mRecyclerView.setAdapter(mAdapter);
Based on the question's comments:
What you're missing there, in RecyclerView's initialisation, is the set of a item animator.
According to your code:
mDataset = new ArrayList<StopResult>();
mRecyclerView = (RecyclerView) findViewById(R.id.results_recycler_view);
mRecyclerView.setItemAnimator(new MyItemAnimator());
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new RecyclerViewAdapter(mDataset, getApplicationContext());
mRecyclerView.setAdapter(mAdapter);
You can refer to this library in order to find an animation that it is best for your needs.