I am programming an app for Android. I uploaded it to GitHub: app
I have a ViewPager (MainActivity.java) controlling two Fragments. On the first Fragment (FirstFragment.java) you can add People (People.java) which appears on the RecyclerView (also on FirstFragment.java). When you click one of the list items on the RecyclerView its details (name and id) appear on the second fragment (SecondFragment.java). The SecondFragment.java also contains a button you can delete the selected People with.
To store the People objects I used a List of People and managed it with the methods in PeopleLab.java. The program was working fine: I could add/remove People objects to the list and it appeared on the RecyclerView fine.
After that, I decided to replace the List with a database. It only meant creating the database (the 3 files in database folder) and editing the already existing and two new methods in PeopleLab.java. The other files remained untouched.
The database is working as expected (checked it with sqlite3), I can add/remove People like before and the queries work. My only problem is that the changes don't appear on the RecyclerView. But if I close and reopen the app, the changes appear.
It's like the RecyclerView doesn't care about the database in runtime, only do when the app starts (or closes, not sure).
Do you have any idea what could cause the problem? My only guess is I miss something about how Android apps handle databases.
P.S.: sorry for my English.
You do call notifyDataSetChanged() on the adapter but you don't provide any new data for that adapter.
In your FirstFragment :
private void updateUI() {
PeopleLab peopleLab = PeopleLab.get(getActivity());
List<People> peoples = peopleLab.getPeople();
if(mAdapter == null) {
mAdapter = new PeopleAdapter(peoples);
mRecyclerView.setAdapter(mAdapter);
} else {
// You actually have to change your dataset
mAdapter.changeDataSet(peoples);
}
}
And in your Adapter :
public void changeDataSet(List<People> people) {
this.mPeoples = people;
notifyDataSetChanged();
}
This some brutal way to do it though.
It would be better to notify your adapter on insertion / removal calling notifyItemInserted(int itemPosition) or notifyItemRemoved(int itemPosition). (And refreshing your dataset, by the way)
It will not work automatically.You can either use to notify the adapter the underlying data has been changed so that adapter can fetch and reload the data.It can be done using adapter.notifyDataSetChanged()
Or use can use CursorLoader to achieve the same
Related
This is my first Android project. I am working on an app for tracking courses in a degree program (this is the project for a course I'm taking). I have set a RecyclerView inside a fragment. At one point the loaded items were not displayed anymore. It was working previously. I only made some changes to other parts of the app, but none to this part. I see no reason for these items to not be showing. I feel like the problem started after I clicked "Install" on an emulator update, which Android Studio suggested. I suspect the update is causing the issue, but I don't know for certain.
The code snippet below is from my fragment. I have downloaded the SQLite database and confirmed that the course.getTermId() matches selectectTerm.getTermId() for 4 items. When I open the fragment, I see a toast message that says "4 Courses loaded", so I know the issue is not with my logic here. I have tried inserting both adapter.notifyDataSetChanged(); and recyclerView.invalidate(); on the blank line right before the toast, but the items still do not show up. I have checked my layout to ensure the RecyclerView is properly sized and anchored. There's clearly something I am missing, but I am simply not seeing it. I have also confirmed that my CourseFlatAdapter does not have any logic errors. No exceptions are printed in Logcat. Does anyone see anything I need to do to fix this?
RecyclerView recyclerView = getView().findViewById(R.id.recyclerCourses);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getContext()));
recyclerView.setHasFixedSize(true);
CourseFlatAdapter adapter = new CourseFlatAdapter();
recyclerView.setAdapter(adapter);
courseViewModel = ViewModelProviders.of(this).get(CourseViewModel.class);
courseViewModel.getAllCourses().observe(this, new Observer<List<Course>>() {
#Override
public void onChanged(List<Course> courses) {
ArrayList<Course> filteredCourseList = new ArrayList<>();
for(Course course : courses){
if(course.getTermId() == selectectTerm.getTermId()){
filteredCourseList.add(course);
}
}
adapter.setCourses(filteredCourseList);
Toast.makeText(ViewTermFragment.this.getContext(), filteredCourseList.size() + " Courses loaded", Toast.LENGTH_SHORT).show();
}
});
I figured it out. One of the changes I had made was to put the fragment container in a ScrollView so the whole thing would be scrollable when there is a large amount of information. The RecyclerView was anchored to the bottom of the fragment and had the height set to MatchParent while the fragment's height was set to WrapContent so the RecyclerView ended having it's height calculated as 0 regardless of how many items it was displaying.
I changed the RecyclerView's height to WrapContent and removed the bottom anchor. It now works as expected. Thank you to everyone who may have spent time on this.
I am making an application that shows a list of my Custom Model. Take example of Facebook News feed. My custom model contains byte arrays of images. For efficiency I am getting only thumb byte arrays.
Now each listView item contain comments, likes and many other things just like Facebook. I am creating a custom adapter in which i am passing Arraylist of my custom Model and showing in ListView.
Everything is working fine however, i am most concerned about memory issues with android. Since i have thumbs to show and also comments and etc.
My listView is inside a Fragment. How can I show listView items that can contain images, Comments etc, without crashing because of memory or slowing down. Example being Facebook feed page. Or more openly, How can I make something similar to Facebook feed page without getting trouble because of Memory or slowing down issues.
What kind of strategy should I adopt
1 - Universal Image Loader To work with images
2 - Use load more in your listview.
Example:
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(this));
list.setOnScrollListener(new PauseOnScrollListener(imageLoader, false, true) {
#Override
public void onScroll(AbsListView view, int firstItem, int itemsInScreen, int totalItems) {
super.onScroll(view, firstItem, itemsInScreen, totalItems);
int lastItemInScreen = firstItem + itemsInScreen;
if (lastItemInScreen == totalItems) {
//load more items in your listview
}
});
TLDR:
I'm setting myListView.setVisibility(View.GONE);, but it's not dissappearing until later... do I need to let it know somehow that I've changed it's visibility? Or do I need to also hide it's inner elements or something?
Description of Problem:
I have a normal news app. You see a list of articles for the "main" section, then you can click the options to select a new section.
When the user clicked, the section title changed, but the articles in the list would just sit there with "old" content until the new content is loaded, then it would flash to the new content.
This isn't ideal obviously. I'd like the list to disappear, show a loading animation, then, after the new data is retrieved (either from DB or online, then DB), it shows the new content.
I found this SO question which seemed like what I want, but...
I'm setting GONE immediately upon selection of the menu, then VISIBLE after it import the articles and loads the new ones... but it's not disappearing at all during that. I know the GONE code works, because if I remove my VISIBLE code, the articles never reappear.
Do I need to say "View.GONE", then tell it to update it's visibility or something?
My Code (MainActivity):
public static void sectionSelected()
{
String selectedText = sectionsSpinner.getSelectedItem().toString();
String[] selectedSection = Section.stringToSection(selectedText);
//check if it was already the current section
if(!Section.isEqual(Section.currentSection, selectedText))
{
//hides list of articles
articleEntryListView.setVisibility(View.GONE);
//sets new currentSection
Section.currentSection = selectedSection; // Section.stringToSection(sectionsSpinner.getSelectedItem().toString());
//imports articles (if it's been more than an hour since last import)
articlesDataSource.importArticles(Section.currentSection, true, false);
//loads article from database to the list
loadArticlesIntoList(Section.currentSection);
}
}
public static void loadArticlesIntoList(String[] section)
{
//clears the list
//articleEntryAdapter.clear(); //don't think I need this now that I'm just going to hide it
//articleEntryAdapter.notifyDataSetChanged();
//POPULATES THE LIST OF ARTICLES, THROUGH THE ADAPTER
for(final Article a1 : articlesDataSource.getArticles(section))
{
articleEntryAdapter.add(a1);
}
articleEntryAdapter.notifyDataSetChanged();
//shows list of articles
articleEntryListView.setVisibility(View.VISIBLE);
}
ADDITION: here is my importAricles() code: http://pastebin.com/8j6JZBej
You have to invalidate the view anytime you make a change to its appearance, so make a call to articleEntryListView.invalidate() after setting the visibility.
i am working on an app to develop my knowledge so far i have created a calendar app which user can make appointment when clicking on a date. i then have a delete button which opens all the appointments created in a fresh activity, there i have: a list view which displays all appointments a textview which displays the selected appointment (selected by the user to delete) and a button remove. the remove button removes all the items from the sqlite but i can only see this working when the application is restarted i know i am missing something else in my code.. how do i clear the listview at the same time any help would be much appreciated
my code:
delete all method
public void deleteAll() {
db.delete(TABLE_NAME, null, null);
}
button code:
public void onClick(View v) {
switch(v.getId()){
case R.id.removeBtn:
dm.deleteAll();
break;
}
thank you
}
Maybe not the most elegant, but I don't build my UI in onCreate(). Instead, in onCreate(), I call another method initializeUI(), and that is where I build my user interface. Then, anytime I do something that should be reflected in the interface (update the database or whatever), I just need to call my method initializeUI() again.
Edit: Also look into notifyDataSetChanged() for your adapter as exampled here
First check if your database is writable (getWritableDatabase)
Then check that your "TABLE_NAME" is in fact the table name.
Then you could try to use execSQL("delete from " + TABLE_NAME);
if that does not work, you could try to close the db.
finally try putting it in a transaction
beginTransaction();
.. delete..
endTransaction();
If you are actually changing the data from the Adapter used in the ListView, you could use requery() method on the cursor used to populate the Adapter. This should reflect your changes!
Hi am working on an android application. And am using a listview in some of my activities.
The problem is all of my listviews displayed are much longer so that the user needs to scroll the whole list to go for the last item.
Am trying to implement a pagination for this, like at first say only 20 items need to displayed on the listview. And at the end of my listview i need a titlebar which have next & previous buttons and on clicking on next button the listview will load the next records from 21st to 40 and so on.
Am using java rest webservice to load the listview.
Can anyone give me a good suggestion for solving my problem.?
Solution 1:
You can load all the data at once if its not TOO MUCH, store it locally & then you can navigate in that locally stored data. Define some variables like StartPoint & EndPoint & get the desired data from that stored data. Increment decrement the values of StartPoint & EndPoint by using the PreviouButton & NextButton.
Solution 2:
Get only the desired data from your data source for example 10 records each time when a Navigation button is clicked.
I suggest than you load list data in a custom Adapter class that extends BaseAdapter class. Like #oriolpons suggested, you should add a footer view, and when you click on button next call some method that is fetching next for example 20 rows, and then add them in your adapter object and call notifyDataSetChanged().
For example
private OnClickListener mListener = new OnClickListener() {
public void onClick(View v) {
ArrayList<YourObject> al = getSomeData(int startRow, int endRow);
MyCustomAdapter adapter = new MyCustomAdapter();
for(YourObject a : al)
adapter.add(a);
getListView.setAdapter(adapter);
notifyDataSetChanged();
}
};
Hope this helps.
The easiest solution is to add a footer view to the listview. And on the item click listener you can see if it is the last position (load more items), or not
//add the footer before adding the adapter, else the footer will not load!
View footerView = ((LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listfooter, null, false);
this.getListView().addFooterView(footerView);
#Tijo . Refer this site http://www.androidhive.info/2012/03/android-listview-with-load-more-button/. You can have a button which would call the execute method of Async task and that will load the remaining list for you.