How to download more Firebase objects on RecyclerView Scroll? - java

I have an app that features chat rooms. Every room has an ID that serves as a database reference, and messages are brought down from there and displayed in a RecyclerView. I know how to increase the number of messages that are downloaded onCreate/onStart by using Query.orderbykey().limittolast(), but how do I download and display additional items when the user scrolls to the top of the RecyclerView of the chat activity, a la Facebook messenger?
Edit: Here is my adapter's construct0r:
public ChatRecyclerViewAdapter(Context mContext, ArrayList<String> mMessage, ArrayList<String> mAuthor, String mRoomID, DatabaseReference reference) {
this.mContext = mContext;
this.mRoomID = mRoomID;
numberOfRecentMessages=20;
messageList = new ArrayList<>();
mDatabaseReference = reference.child(mRoomID+"_messages");
recentMessages = mDatabaseReference.orderByKey().endAt(100).limitToLast(numberOfRecentMessages);
recentMessages.addChildEventListener(mListener);
}

It sounds like you're looking for endAt(), which takes the key of the last item to return. Say you you're currently showing these keys:
key20
key21
key22
key23
key24
key25
key26
key27
key28
key29
Then you can get the previous items with:
ref.orderByKey().endAt("key20").limitToLast(11)

Related

Click on tag and view only picture with the same tag

I wouldlike to when I click on tag of one of my picture to view only pictures with the same tag.
In this picture an example of what I want :
Photo
private void initRecyclerView(){
mImageUrls.add("https://c1.staticflickr.com/5/4636/25316407448_de5fbf183d_o.jpg");
mNames.add("Havasu Falls");
mtags.add("#Sun");
mImageUrls.add("https://i.redd.it/0h2gm1ix6p501.jpg");
mNames.add("Mahahual");
mtags.add("#Sun");
mImageUrls.add("https://i.redd.it/k98uzl68eh501.jpg");
mNames.add("Frozen Lake");
mtags.add("#Winter");
RecyclerView recyclerView = findViewById(R.id.recycler_public);
MyRecyclerViewAdapter MyRecyclerViewAdapter = new MyRecyclerViewAdapter(this, mNames, mImageUrls, mtags);
StaggeredGridLayoutManager RecyclerGridLayoutManager = new StaggeredGridLayoutManager(1, LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(RecyclerGridLayoutManager);
recyclerView.setAdapter(MyRecyclerViewAdapter);
}
You must...
Create a model/pojo class to store details like url, name and tag.
Create two list of your pojo class. (ArrayList) one for all data and one for filtered data.
When user clicks on tag...filter your data with that clicked tag and display that list in a recyclerView.
In short use 'Filterable' for recyclerview see this https://www.androidhive.info/2017/11/android-recyclerview-with-search-filter-functionality/

Pass number of repeated database column instances into TextView with CursorAdapter

I am fairly beginner and currently writing an app which contains a list of Restaurants. I am using a SQLite database to store the "Restaurant" objects and am using a CursorAdapter to display them into a ListView.
Currently the fields are a photo, the name of the restaurant and its location.
I want to have one more TextView which shows how many times that certain restaurant appears in the database. I'm having trouble figuring out how to do this inside my CursorAdapter class.
Below is my bindView method in the CursorAdapter class where the existing views get updated.
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Find individual views that we want to modify in the list item layout
ImageView foodImageView = (ImageView) view.findViewById(R.id.food_image_view);
TextView restaurantNameTextView = (TextView) view.findViewById(R.id.restaurant_name_text_view);
TextView restaurantLocationTextView = (TextView) view.findViewById(R.id.restaurant_location_text_view);
// Find the columns of restaurant attributes that we're interested in
int foodPictureColumnIndex = cursor.getColumnIndex(RestaurantEntry.COLUMN_FOOD_PHOTO_URL);
int restaurantNameColumnIndex = cursor.getColumnIndex(RestaurantEntry.COLUMN_RESTAURANT_NAME);
int restaurantLocationColumnIndex = cursor.getColumnIndex(RestaurantEntry.COLUMN_RESTAURANT_LOCATION);
// Read the restaurant attributes from the Cursor for the current restaurant
String foodPhoto = cursor.getString(foodPictureColumnIndex);
String restaurantName = cursor.getString(restaurantNameColumnIndex);
String restaurantLocation = cursor.getString(restaurantLocationColumnIndex);
// Update the Views with the attributes for the current restaurant
Picasso.with(mContext).load(foodPhoto).into(foodImageView);
restaurantNameTextView.setText(restaurantName);
restaurantLocationTextView.setText(restaurantLocation);
}
Answered my own question; used a temporary ArrayList to track how many times a certain name appears in the database table

Android - Design trouble - Should I use setTag to hold information for OnClick event?

I'm doing a small project as part of the Android course.
The app is supposed to retrieve the most popular movies using some site's API and then display them in a grid view (using posters as thumbnails).
When a specific movie is clicked a new activity will be started providing details.
I've gotten this far:
Obtained a list of most popular movies poster image URL's using the website's API.
Implemented an adapter extending ArrayAdapter which accepts ArrayList as the data source and loads the image from URL into ImageView item.
Populated the GridView using the adapter.
Setup listeners on Gridview using this code:
s:
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
//do stuff according to position/view
}
The info I need to pass onto the movie details activity when a movie is clicked can be obtained in step 1 (I just extracted the poster URLS from the json).
To be able to even provide information when a view is clicked I need to (at the very minimum) also extract the movie's ID and store it.
So as it seems my options are:
Store the IDs in the adapter. Then when a click occurs use getItem(position) to obtain the ID and send it with the intent. The next activity will then have to query the server for the movie details.
This means creating a class:
static class MovieItem {
int Id;
string posterUrl;
}
And converting the adapter to use ArrayList<MovieItem>.
Same as option 1 but instead use setTag to store the Id of the movie.
Same as option 1 but instead obtain all the required information (title, rating, plot, etc..) and store it to MovieItem. Query not required in the next activity.
Same as option 3 but instead use setTag (MovieItem). Query not required in the next activity.
I'm new to app development and I'm trying to get things done the right way, Would appreciate some help.
EDIT:
Also wanted to add, if I had stored additional movie information in the adapter would that not have been appropriate because the information isn't relevant to that class?
Thanks for your troubles! :)
When you first request the list of Movie info, you could store the details for each movie in something like a HashMap<String, HashMap<String, String>>, where the String is the movie id, and the Map is a set of Key/Value pairs for details information. Then, when a click comes through on your onClick, you would use the position to determine which movie poster was clicked. You would then retrieve the details HashMap for the selected movie, put it into a Bundle, pass it to the Intent of your new Activity, then retrieve it on the other side. So the code would look something like this:
When you first retrieve your list of movies, you would do something like this:
//You would put each set of movie data into a HashMap like this...
HashMap<String, HashMap<String, String>> movies = new HashMap<>();
HashMap<String, String> details = new HashMap<>();
details.put("dateReleased", "7.12.2015");
details.put("rating", "PG-13");
details.put("title", "Cool Awesome Movie");
movies.put("12345", details);
//Then when an onClick comes in, you would get the set of
//details for the movie that was selected (based on position)
HashMap<String, String> selectedDetails = movies.get("12345");
//Put the retrieved HashMap of details into a Bundle
Bundle bundle = new Bundle();
bundle.putSerializable("movieDetails", selectedDetails);
//Send the bundle over to the new Activity with the intent
Intent intent = new Intent(this, YourDetailsActivity.class);
intent.putExtras(bundle);
startActivity(intent);
Then when the new Activity starts, you would retrieve the details from the Bundle in your onCreate():
//Then in onCreate() of the new Activity...
Bundle bundle = getIntent().getExtras();
HashMap<String, String> movieDetails = (HashMap<String, String>) bundle.getSerializable("movieDetails");
String dateReleased = movieDetails.get("dateReleased");
String rating = movieDetails.get("rating");
String title = movieDetails.get("title");

Android Array Adapter with ArrayList and ListView not updating when the arraylist is changed

I have an android app with a screen that comprises of a ListView, which I am using to display a list of devices. These devices are held in an array.
I am trying to use the ArrayAdapter to display what is in the array on the screen in a list.
It works when I first load the SetupActivity class, however, there is the facility to add a new device in the addDevice() method, which means the array holding the devices is updated.
I am using notifyDataSetChanged() which is supposed to update the list but it doesn't seem to work.
public class SetupActivity extends Activity
{
private ArrayList<Device> deviceList;
private ArrayAdapter<Device> arrayAdapter;
private ListView listView;
private DevicesAdapter devicesAdapter;
private Context context;
public void onCreate(Bundle savedInstanceState) //Method run when the activity is created
{
super.onCreate(savedInstanceState);
setContentView(R.layout.setup); //Set the layout
context = getApplicationContext(); //Get the screen
listView = (ListView)findViewById(R.id.listView);
deviceList = new ArrayList<Device>();
deviceList = populateDeviceList(); //Get all the devices into the list
arrayAdapter = new ArrayAdapter<Device>(this, android.R.layout.simple_list_item_1, deviceList);
listView.setAdapter(arrayAdapter);
}
protected void addDevice() //Add device Method (Simplified)
{
deviceList = createNewDeviceList(); //Add device to the list and returns an updated list
arrayAdapter.notifyDataSetChanged(); //Update the list
}
}
Can anyone see where I am going wrong?
For an ArrayAdapter, notifyDataSetChanged only works if you use the add, insert, remove, and clear functions on the Adapter.
Use clear to clear the adapter - arrayAdapter.clear()
Use Adapter.addAll and add the newly formed list - arrayAdapter.addAll(deviceList)
Call notifyDataSetChanged
Alternatives:
Repeat this step after new devicelist is formed - but this is
redundant
arrayAdapter = new ArrayAdapter<Device>(this, android.R.layout.simple_list_item_1, deviceList);
Create your own class derived from BaseAdapter and ListAdapter that
gives you more flexibility. This is most recommended.
While the accepted answer solves the problem, the explanation of why is incorrect, and since this is an important concept I thought I'd attempt to clarify.
Slartibartfast's explanation that notifyDataSetChanged() only works when add, insert,remove, or clear is called on the adapter is incorrect.
That explanation is true of the setNotifyOnChange() method, which if set to true (as it is by default) will automatically call notifyDataSetChanged() when any of those four actions occur.
I think the poster confused the two methods. notifyDatasetChanged() itself does not have those restrictions. It just tells the adapter that the list it is looking at has changed, and it does not matter how the change to the list actually happened.
While I can't see the source code for your createNewDeviceList(), I would guess your problem came from the fact that you had the adapter referencing the original list you created, and then you created a new list in createNewDeviceList(), and since the adapter was still pointing to the old list it could not see the changes.
The solution slartibartfast mentioned works because it clears the adapter and specifically adds the updated list to that adapter. Thus you don't have the problem of your adapter pointing to the wrong place.
Hope this helps someone!
your method addDevice is causing an endless loop. Dont call a method from itself like you are doing here :
deviceList = addDevice();

java android load items to listview from database?

Okay so i have a database, and i want it so you can favorite items.
Would i make it so you can save items then it will load it into a list view?
this is my load thing
//Calls the database, gets a list of names.
// if listofnames.size()==0 keep name, otherwise
// change name to first name.
ArrayList<String> nameList = new ArrayList<String>();
favList = db.getName();
if(favList.size()>0){
name.setText(favList.get(0));
But that just sets a text i want it to add items..
You may use ArrayAdapter or SimpleAdapter or BaseAdapter - through which you may bind dataSource (List<T>) to the ListView.
You can do this as follows
public class MyClass extends ListActivity{
public void onCreate(Bundle bundle){
//get the names from database
setListAdapter(new ArrayAdapter<E>(this,R.layout.xml_filename,your_list);
}
}
Remember in this case your xml file should be the TextView (I.e the items what list view should contain). You cannot pass an xml file with a ListView directly.
If you have still some problem, then post your code which can be solved.
You can follow the given link for more clarification.
http://developer.android.com/resources/tutorials/views/hello-listview.html

Categories