Android increasing database performance - android

Well I hava a listview and if clicked a listview element a Viewpager openning to show content.
both listview and Viewpager are same adaptor which is coming from database.
The problem is: when viewpager openning it needs to create same list adaptor to use.
How can I use Listview's list for viewpager without creating again and again.
I take this codes from Big Nerd's book:
This is listfragment:
public class framelist extends ListFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
TestAdapter mDbHelper = new TestAdapter(getActivity());
mDbHelper.createDatabase();
mDbHelper.open();
List<element> mElements = mDbHelper.getTestData();
This is Viewpager FragmentActivity
public class CrimePagerActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewPager = new ViewPager(this);
mViewPager.setId(R.id.viewPager);
setContentView(mViewPager);
TestAdapter mDbHelper = new TestAdapter(this);
mDbHelper.createDatabase();
mDbHelper.open();
mElements = mDbHelper.getTestData();
And this is Viewpager fragment:
public class CrimeFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mNum2 = (int) getArguments().getInt("num");
TestAdapter mDbHelper = new TestAdapter(getActivity());
mDbHelper.createDatabase();
mDbHelper.open();
List<element> mElements = mDbHelper.getTestData();
melement = mElements.get(mNum2);

I suggest you use the Loader framework in order to query things. If nothing else, refer to my answer to similar question, it provides some very relevant links, that could help you in your case study.
One more hint: if you just use straightforward approach, which is "query database through OpenSqliteDbHelper instance from your Activity", you have to be very careful and take care about your app lifecycle and Cursor's lifecycle management. And of course, it is very hard to improve performance, if you use such approach. All these problems disappear like magic if you use the suggested Loader approach, as it persist data on configuration change and you do not have to query your data again and again.
One more hint: if you choose to use the straightforward (that is, without Loader) approach, make sure you query your data on a separate thread. That will keep your UI from being frozen.
Similar questions were already asked and answered here, use search, if nothing else

What are you trying to achieve by showing the same content in both list as well as viewpager
Anyway, in your CrimePagerActivity instead of recreating a list again, why not copy the contents to the list
List<element> newList = mDbHelper.getTestData();
mElements.clear();
mElements..addAll(newList);
One more advice, your subject says increasing db performance , but you are asking all about list
Follow singleton pattern for DB and donot create new DB everytime, and make sure you synchronize any calls to db

Related

Saving items in listview when added from another activity

I have a listview of items in my ShoppingListActivity.
Items are added from another activity thought an intent. I want to make sure that all items are kept in the list when going between both activities; however, right now my list only has the last item added from the previous activity.
My ShoppingListActivity.class
public class ShoppingListActivity extends Activity {
private ListView mainListView ;
private ArrayAdapter<String> listAdapter ;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shopping_list);
// Find the ListView resource.
mainListView = (ListView) findViewById( R.id.mainListView );
ArrayList<String> shoppingList = new ArrayList<String>();
shoppingList.add(itemLookup());
// Create ArrayAdapter using the shopping list.
listAdapter = new ArrayAdapter<String>(this, R.layout.simplerow, shoppingList);
// Set the ArrayAdapter as the ListView's adapter.
mainListView.setAdapter( listAdapter );
}
//Lookup item by ID
public String itemLookup() {
String itemName = "";
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (intent != null) {
String itemId = extras.getString("BARCODE_ID");
try {
itemName = ItemLookup.lookupById(itemId);
} catch (IOException e) {
e.printStackTrace();
}
}
return itemName;
}
#Override
public void onBackPressed() {
startActivity(new Intent(ShoppingListActivity.this, MainActivity.class));
}
}
I have a feeling I should be putting my add somewhere else. I'm pretty sure I should be passing the list back and forth in a putExtra, but if that's how I have to do it, it's fine.
How can I make sure that the list is maintained between activities?
One way around your problem is Singleton Pattern.
In your case you can implement something like this:
public class ShoppingListManager {
private static ShoppingListManager instance = new ShoppingListManager();
private List<String> shoppingList;
public static ShoppingListManager getInstance() {
return instance;
}
public List<String> getShoppingList() {
return shoppingList;
}
// Make the constructor private so that this class cannot be instantiated
private ShoppingListManager(){
shoppingList = new ArrayList<String>();
}
}
Then access it anywhere in your code.
ShoppingListManager.getInstance().getShoppingList();
One point to remember never store context in singleton classes as it will lead to memory leaks.
Keeping your data structures in an Activity makes your app prone to data loss because Activities can be destroyed at various times and for a variety of reasons, including rotating the device between portrait and landscape.
You should use a separate class to store and track which items are in the shopping list. The Activity with the ListView should only get the list of items stored and display them. Anything that causes an item to be added should simply trigger a reload of the list (if the Activity is running in the foreground), otherwise the Activity should see that new item anyway the next time it starts.
If you also need your data to be persistent after your process is terminated, you should look into the possible data storage options available.

How to update a fragment?

I have Messanger App that has a Master/Detail Flow Layout with 2 fragments. I used the template provided by Android Studio.
When the ListFragment is in the foreground and a new user logs in the ListView is not immediately updated and the User does not appear on the List.
When I select a different activity and go back to the ListFragment afterwards the list is updated.
this is where my data is stored. If a new user logs in the addUser method is called and this adds the user to the List and Map.
public static List<ChatContent> ITEMS = new ArrayList<ChatContent>();
public static Map<String, ChatContent> ITEM_MAP = new HashMap<String, ChatContent>();
protected static void addUser(ChatContent userChatContent) {
ITEMS.add(userChatContent);
ITEM_MAP.put(userChatContent.user, userChatContent);
}
This is how I set the listAdapter in the onCreate method of the ListFragment.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayAdapter arrayAdapter = new ArrayAdapter<ChatData.ChatContent>(
getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1,
ChatData.ITEMS);
setListAdapter(arrayAdapter);
}
FYI: The same thing happens when I'm on the detailsFragment and a new chat message arrives: the message does not appear unless I leave the activity and come back.
When you update your data ,you should use these code to update the UI.
arrayAdapter.notifyDataSetChanged();

update listview from fragment within viewpager from main activity

COMPLETELY EDITED
Ok I will try to be more specific.
I'm developing a small app drawer. Therefore I need a way to let the user choose categories.
This is the main point of the question. If there is another better way than my approach please let me know.
So my try to implement this was to load all apps to an array list and save this to a service to make it available throuout the app. The loading of the apps is done by an asynctask.
MainActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
packageManager = getPackageManager();
if ((AppDrawerService.getApps()) == null) {
apps = new ArrayList<ApplistItem>();
loadAppsToService();
} else {
//if Service already holds the data
manageViews();
}
}
private void loadAppsToService() {
LoadApplications loadApps;
loadApps = new LoadApplications(this);
loadApps.setOnLoadApplicationsFinishedListener(this);
loadApps.execute();
}
private void manageViews() {
FragmentManager fragmentManager = getSupportFragmentManager();
myViewPager = (ViewPager) findViewById(R.id.view_pager);
myViewPager.setAdapter(new ViewPagerAdapter(fragmentManager, this));
}
#Override
public void OnLoadApplicationsComplete(ArrayList<ApplistItem> apps) {
manageViews();
}
LoadApplications:
#Override
protected void onPostExecute(Object o) {
AppDrawerService.setApps(apps);
listener.OnLoadApplicationsComplete(apps);
super.onPostExecute(o);
}
ViewPagerAdapter:
#Override
public Fragment getItem(int position) {
Fragment category = null;
category = new AppListFragment()
return category;
}
#Override
public int getCount() {
pages = 5;
return pages;
}
AppListFragment:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if ((AppDrawerService.getApps()) == null) {
apps = new ArrayList<ApplistItem>();
} else {
apps = AppDrawerService.getApps();
}
v = getActivity().findViewById(android.R.id.list);
myApplist = (ListView) v;
applistAdapter = new ApplistAdapter(context, 0, apps);
myApplist.setAdapter(applistAdapter);
myApplist.setOnItemClickListener(this);
}
The problem which I have with this code is, that it alway populates only one Fragment with the applist. On first start the first fragment is populated with the apps but if you swipe two fragments to right and then one back to left, this fragment (the second) is populated. The impression which I have is that the
return new ApplistFragment();
from the ViewPager does actually not create an independent instance of the fragment. (At least I think so)
What I want is to show an undefined amount of Fragments which can all show different categories of the same list. So if possible I want to load the list only once and I want to reuse the Fragment code for every fragment since I don't want to restrict the max amount of categories.
My idea was to use the ApplistAdapter to filter the unwanted apps for every category but I really don't know.
Help is really really appreciated since I have no idea how to go along.
Thanks in advance.
I would change how this works all together. A few suggestions of the top of my head:
Download the data in the Service instead of the Activity and
persist it somewhere for example in a database.
You can use an Intent to tell the Service what you want to download and when to do it.
You can also use an IntentService instead of a Service.
IntentServices already handle each Intent in a separate worker
thread so you don't need an AsyncTask or anything like that in the
IntentService to perform the downloading.
Each Fragment should load the data from the database in onResume(). You
can use local broadcasts to inform the Fragments when the data
changed while they are being displayed.
If you don't give us more information it will be difficult to give you very specific advice.

android - pass data from one activity to a list in a second activity

new to droid programming. im having a small problem that im sure is simply fixed but ive done some searching and a bunch of tutorials but cant seem to find just what i need so i figured id ask. My app has 2 activites, the first activity is just a simple form where a user enters course information(class title, professor..etc.)
the first activity passes the data which is supposed to be stored in a list in the second activity. problem is that only the first course gets stored in the list, after the first time nothing new gets added to the second activity. Can someone point me in the right direction please? thanks in advance
First Activity
public class CourseDetail extends Activity {
//Course c = new Course();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button save=(Button)findViewById(R.id.save);
save.setOnClickListener(onSave);
}
private View.OnClickListener onSave=new View.OnClickListener() {
public void onClick(View v) {
EditText course=(EditText)findViewById(R.id.course);
EditText professor=(EditText)findViewById(R.id.professor);
EditText location=(EditText)findViewById(R.id.location);
EditText officehrs=(EditText)findViewById(R.id.officehrs);
Intent i=new Intent(CourseDetail.this, CourseList.class);
i.putExtra("myCourse", course.getText().toString());
i.putExtra("myProfessor", professor.getText().toString());
i.putExtra("myLocation", location.getText().toString());
i.putExtra("myOfficehrs", officehrs.getText().toString());
startActivity(i);
}
};
}
Second Activity
public class CourseList extends Activity {
Button btnCourse;
List<Course> model = new ArrayList<Course>();
CourseAdapter adapter=null;
private String dCourse="";
private String dProfessor="";
private String dLocation="";
private String dOfficehrs="";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.clist);
ListView list =(ListView)findViewById(R.id.courses);
adapter=new CourseAdapter();
list.setAdapter(adapter);
Course c = new Course();
Bundle extras = getIntent().getExtras();
dCourse = extras !=null ? extras.getString("myCourse") :"no value entered";
dProfessor = extras !=null ? extras.getString("myProfessor") :"no value entered";
dLocation = extras !=null ? extras.getString("myLocation") :"no value entered";
dOfficehrs = extras !=null ? extras.getString("myOfficehrs") :"no value entered";
c.setCourse(dCourse);
c.setProfessor(dProfessor);
c.setLocation(dLocation);
c.setOfficeHrs(dOfficehrs);
btnCourse =(Button)findViewById(R.id.btnCourse);
btnCourse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
finish();
}
});
}
You are just getting the user entered value in CourseDetail activity and displaying the received value inside the CourseList activity, that means you are not storing these values permanently.
Go through this Android - Data Storage document.
When you move to 2nd activity i.e. CourseList activity, at that time fetch the data from the SQLite table and display the same. whenever you get new values from previous activity, at that time just update the list by adding the new data in ArrayList and make a call on adapter.notifyDataSetChanged()
Some suggestions:
Have your CourseList extend ListActivity instead of just Activity - check out some tutorials on that which should help you set things up correctly.
There seems to be a bit of confusion with how you're handling your lists - you have your model variable but don't seem to be doing anything with it. Again, have a look at a ListView tutorial (just google "android listview tutorial").
You seem to have figured out that you can use "intents" to pass information from one activity to another, but since you're only doing this in the onCreate() method, it's only happening once. Try doing this in your ListActivity's adapter once for each item.
Don't give up on Android, keep trying :-)
Some suggestion:
You have to add your object to the adapter: adapter.add(c); after you get the data.
Call adapter.notifyDataSetChanged() to notify the system that your data for the listView has been changed. Call list.invalidate() to refresh it.
I noticed that you set the button with the finish() method. Hmm, if you do so, the next time you get to CourseList Activity from CourseDetail, the adapter will be null again. No previously received data will be available. Is this what you really want?
The problem is you are not adding the newly added items to the List.So before setting adapter you have to add all your objects like
list.add(c);

Android ListView refresh issue

I'm getting a weird problem when refreshing my ListView, it works fine until the device is rotated and then when refreshing it again it goes completely blank. This can only be fixed by rotating the device again(as it is also refreshed in onCreate()) but then whenever its refreshed again it goes blank. Problem persists until app is restarted.
EDIT:
Some code:
private ListView contactlist = null;
private static MatrixCursor matrixcursor = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
contactlist = (ListView) findViewById(R.id.contactlist);
if (savedInstanceState == null) {
matrixcursor = new MatrixCursor(new String[] {"_id","name","one","two","three","four"});
} else {
contactlist.setAdapter(new listCursorAdapter(this,matrixcursor));
}
}
this works fine but whenever:
contactlist.setAdapter(new listCursorAdapter(this,matrixcursor));
is called after onCreate() and after the device has been rotated the ListView goes blank.
I think your MatrixCursor is actually null. When you rotate the phone as you know the activity is destroyed. So the savedinstanceState bundle might not be null but the MatixCursor then does not get reinitialized. Yes it's static but I have a feeling if it for some chance it's not loaded in the same classloader ... well that static is not going to be too reliable.
There is a method which is most awkwardly named:
onRetainNonConfigurationInstance()
Which I think will help you solve this case. So if you return your MatrixCursor instance there, you can in a later call to onCreate() use getLastNonConfigurationInstance() to read the data back out. It's not guaranteed to be called, so you will still need to handle the case where you have no stored state. Hopefully this helps.
private ListView contactlist = null;
private MatrixCursor matrixcursor = null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
contactlist = (ListView) findViewById(R.id.contactlist);
matrixcursor = (MatrixCursor)getLastNonConfigurationInstance();
if (matrixcursor == null) {
matrixcursor = new MatrixCursor(new String[] {"_id","name","one","two","three","four"});
} else {
contactlist.setAdapter(new listCursorAdapter(this,matrixcursor));
}
}
public MatrixCursor onRetainNonConfigurationInstance() {
return matrixcuror;
}
public MatrixCuror getLastNonConfigurationInstance() {
return (MatrixCursor) super.getLastNonConfigurationInstance();
}
Well I managed to fix it by making contactlist static:
private static ListView contactlist = null;
I have no idea why this worked(just did a trial/error for a couple of hours) so if anyone could explain it that would be great.

Categories

Resources