Passing a cursor to an activity? - android

Is this possible? I am trying to open a SQLite database cursor in one activity, and pass it to another activity.

Another way to do this which might be easier is to create an Application class for your app. This is guaranteed to be created only once, and exists for the lifetime of your app. Among other things, it can provide a "data hub" capability for your app so different Activities can share data easily. So, for your cursor, you'd simply use a member variable of the Application class like so (warning, I copied this code from my app and edited it here, so no guarantee of compilation. Just something to show the idea.):
package com.jcascio.k03;
import android.app.Application;
import android.database.Cursor;
// use your application's name instead of "K03Application"
public class K03Application extends Application {
public final String TAG = "K03";
Cursor sharedCursor; // this cursor can be shared between different Activities
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onTerminate() {
super.onTerminate();
}
public Cursor getSharedCursor()
{
return this.sharedCursor;
}
public void setSharedCursor(Cursor c)
{
this.sharedCursor = c;
}
}
The application object can be fetched from any Activity using
this.getApplication()
// You cast it to your Application sub-class and call the Cursor accessor function
Cursor c = ((K03Application)this.getApplication()).getSharedCursor();
So, your first Activity would fetch some goo from the database, which is returned to it as a Cursor. This activity would call setSharedCursor in the application. Then it would launch the second Activity, which would call getSharedCursor in its onCreate function (or any other function for that matter) to retrieve the cursor.

I personally don't know of any simple ways to do this. It might be easier just to make the query again in the destination activity.

You should write your own Cursor which will implement Parcelable interface. In this case you can put your cursor to parcel and send it to another Activity through putExtra(). In target Activity you can explode (in fact just find it through handler) Cursor through one of Parcel methods (related to Binder).

Related

Pass MatrixCursor of data from Activity to Fragment

The core of this question is how to send a MatrixCursor of data from an activity to a fragment.
I am doing my search functionality in my activity and am returning a fragment which contains a list that will be filled with data from the query response that is a Matrix Cursor.
Bundle and parcelable thus far are not working out for me. Any tips or guidance?
I see three potential options.
Try Gson. You may be able to convert the instance to a String to pass it and then reinstantiate it from the String data. However, this doesn't work for everything.
Create a new method in your Fragment. You're not meant to pass custom arguments in the constructor, but you could pass it later:
private MatrixCursor cursor;
public void setCursor(MatrixCursor cursor) {
this.cursor = cursor;
}
Since it's the same instance, changes made to the one in your Fragment will be reflected in your Activity. However, this will cause issues if you rotate your device or cause another configuration change. To fix that, add the following to your <activity> attribute in your Manifest:
android:configChanges="orientation|keyboardHidden"
Fragments retain a reference to their parent Activity. You could add helper methods to your Activity that essentially proxy the ones you need from your MatrixCursor instance:
public void addRow(Object[] columnValues) {
cursor.addrow(columnValues);
}
//etc
Then, in your Fragment, you can do:
((MyActivityClass) getActivity()).addRow(columnValues);
Option 3 would probably be the best option, since it doesn't rely on something that might not work or what's basically a hack.
Make a interface Searchable
public interface Searchable {
MatrixCursor getSearchResult()
}
make sure you implement this interface to your activity.
public MainActivity extends AppCompatActivity implements Searchable {
private MatrixCursor mSearchResultMatrixCursor;
...
#Override public MatrixCursor getSearchResult() {
return mSearchResultMatrixCursor;
}
}
In you Fragment's onCreate or wherever you want to use MatrixCursor,
you can call,
if(getActivity != null && getActivity instanceOf Searchable) {
MatrixCursor matrixCursor = ((Searchable)getActivity).getSearchResult()
}
This will persist as long as activity is not recreated.

How can Main Activity call another Activity A and send its context to it?

My MainActivity calls another Activity A which needs to access some members of MainActivity.
What is the best way to send a reference to Main Activity (or its context) to Activity A without resorting to complicated methods like parcelables etc?
There are some heavyweight android wrestling matches here but I am not sure that it is relevant to my problem.
details
I have Alert and Alerted objects in a one-to-many relationship (Alerted represents the various times an Alert was rung).
AlertsListActivity extends ListActivity which displays a list of Alert objects from a SQLite database table (primary key: alertId). It has an AlertsListAdapter.
AlertedsListActivity has a ListFragment which displays a list of Alerted objects from Alerted table (foreign key is alertId from Alert table).
It has an AlertedsListAdapter.
AlertsListActivity needs to call AlertedsListActivity to display the list of Alerted objects. I used startActivityForResult().
Inside AlertedsListAdapter
public View getView(int position, View convertView, ViewGroup parent) {
final Alert alertItem = (Alert) mainActivity.alertsListAdapter.getItem(position);
final Alerted alertedItem = (Alerted) getItem(position);
...
I do need the Alert objects also, in order to display some identifying information from them with each Alerted list item. Hence I need the reference to mainActivity.alertsListAdapter
How can AlertedsListActivity access AlertsListActivity?
Update: Since I did not get any solutions, I implemented a workaround. The data that I needed to access from Main Activity, I modified. So the Alert object was made a parcelable, and the SQLOpenHelper was made a singleton.
This allows the data to be accessed from Activity A.
Here's the simple, common way to do it:
singletons typically have variables like the below example, "useThisContext" or "mainFeedIsHere".
public class Cloud
{
private static Cloud ourInstance = new Cloud();
private Cloud() { Utils.Log("cloud singleton launched"); }
public synchronized static Cloud getInstance()
{
return ourInstance;
}
/////////////////////////////////////////////////
public Context useThisContext;
another example ...
public class Feed
{
private static Feed ourInstance = new Feed();
private Feed()
{
Utils.Log("feed singleton launched");
freshestPostsForDisplay = new ArrayList<ParseObject>();
}
public synchronized static Feed getInstance()
{
return ourInstance;
}
public List<ParseObject> freshestPosts;
public MainActivity mainFeedIsHere;
Quite simply when everything launches (or when it changes), those "things" need to set those variables in the singleton. In other words, those things "tell the singleton, where they are." It's that simple.
So, in the MainActivity perhaps, in onCreate, it might say something like...
CLOUD.useThisContext = this;
FEED.mainFeedIsHere = this;
Then for example inside Feed.java you may have say
mainFeedIsHere.feedReload();
It goes without saying you have to check that they are not null (but how else could it be?) and you have to keep them up-to-date as it were. (i.e., for whatever reason you may want to change "useThisContext" -- again how else could it be?)
{Sometimes you'll have one "centralised" singleton .. perhaps "State" .. to sort of combine all these together - so that anyone can "get to" any of those "exposed" things as needed. This is, really, how game engines go; so that you can say more or less SoundEffects.Booms() or Tanks.Faster() or AI.FindVillains() at any time anywhere.}
Cheers!
Since I did not get any solutions, I implemented a workaround. The data that I needed to access from Main Activity, I modified. So the Alert object was made a parcelable, and the SQLOpenHelper was made a singleton.
This allows the data to be accessed from Activity A.

SQLite database in separate class vs. in same class, which is better? Android

I have an SQLite database that is in a separate class from the main class that extends Activity.
I noticed that there are two ways of setting up the database. one way is to put it inside the main Activity class, either in the class or as a nested sub class. the second way is to put it in the separate class.
the separate class looks better, however there is one disadvantage. You have to create an instance of it in the main activity class every time you want to do something. I read that instantiating objects in Android is expensive and should be avoided.
despite this, I would rather make the database as a separate class. Is the cost of instantiating objects enough that it makes putting the database in the same class a better deal?
example of separate class for SQLite database: incomplete psudo-code
public class SQLiteDB {
private static class DbHelper extends SQLiteOpenHelper{
// db helper methods
}
// methods for DB, like get, set, and others
public void openDatabase(){ }
public void closeDatabse(){ }
public void insertRecord(String record){ }
}
example use in main Activity: incompete psudo-code
public class Main extends Activity{
// every time I want to use it I must instantiate an object for the database class
// many instances of SQLiteDB object created, garbage collector works hard
SQLiteDB mDatabase = new SQLiteDB();
openDatabase();
insertRecord("insert this");
closeDatabase();
}
SQLite database in separate class vs. in same class, which is better?
This is very comprehensive question and it depends on more factors(type of application, personal requirements, how you'll deal with db etc.). Somebody can prefer to place database as inner class and someone as separated class. Problem is that many developers are trying to "stick" as much code as possible into one class and maybe they "fear" to create a little more classes. I don't know that exactly. I mentioned that only as my personal note.
But let's back to your question. What is better?
I think that approach with separeted class. You should let your Activity classes only "Activity classes" > only for creating and dealing with UI. Application appearance should be separated from application logic. If you'll follow this "rule" your code will become more clean and human-readable(if someone else will look at your code he shouldn't be completely lost). It's not a shame to have 20 purely written classes as to have all stuff sticked in one class(like a pig).
however there is one disadvantage. You have to create an instance of
it in the main activity class every time you want to do something. I
read that instantiating objects in Android is expensive and should be
avoided.
Did you think about an usage of Singleton? This design pattern is worth to think about it. You will always have only one instance that have many benefits e.q. no waste of memory. I have only good experiences with Singleton. Therefore i recommend you to try and use it.
Example:
private static SQLiteOpenHelper instance;
public static SQLiteOpenHelper getInstance(Context mContext) {
if (instance == null) {
instance = new SQLiteOpenHelperImplementation(mContext);
}
return instance;
}
And at the end i give you a few suggestions:
Everytime you'll work with cursors, databases etc. release / close
them immediately after work is done. This can solve many exceptions
related to SQLiteDatabase and Cursor
An usage of synchronized blocks and methods is pretty good practise
in the case of concurrent programming to avoid many problems
If you have more than one table in database i suggest you create
"serving" class for each table that will wrap CRUD operations and specific
methods of the table
Before Activity is destroyed, check and release all sources which are not
already released.
I prefer the solution you gave here. The primary advantage is that you can easily access the database from any Activity (or other class) in your app. To solve the problem of creating a new instance every time you use the database, you can instead create a single instance in onCreate(), use the database all you want while the Activity is active, and finally close the database in onDestroy().
This would be a matter of personal taste.
However, what I've found to be efficient and clean has been to create a class that extends SQLiteOpenHelper. In this class you will end up writing the SQL code to create your tables and writing methods as your stored procedures.
The class would look something like this:
public class DatabaseInterface extends SQLiteOpenHelper {
// Database version
private static final int DATABASE_VERSION = 1;
public DatabaseInterface(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
//in your oncreate you will write the queries to create your tables
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_NEWS = "CREATE TABLE News(id INTEGER)";
db.execSQL(CREATE_NEWS);
}
// upgrading tables
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// drop tables if exist
db.execSQL("DROP TABLE IF EXSIST " + NEWS);
// recreate tables
onCreate(db);
}
Consider we have a News obj that takes 1 param as it's constructor, your stored procedures can look something like this:
public ArrayList<News> getNews() {
ArrayList<News> mNewes = new ArrayList<News>();
SQLiteDatabase db = null;
Cursor cursor = null;
try {
String sQry = "SELECT * FROM " + NEWS;
db = this.getWritableDatabase();
cursor = db.rawQuery(sQry, null);
if (cursor.moveToFirst()) {
do {
mNewes.add(new News(cursor.getInt(0)));
} while (cursor.moveToNext());
}
} catch (SQLiteException e) {
Log.e("SQLite - getNewes", e.getMessage());
return null;
} finally {
cursor.close();
db.close();
}
return mNewes;
}
In the above method you get and open the application database preform the query on it, anticipating any sql errors and then close the database. Doing it this way assures that you never have any resources open that you don't need/aren't using.
I've used this method in two apps that are currently out in the market and it runs rather quickly with making several hundred calls to methods I created for my stored procedures

How can I call getContentResolver in android?

I'm writing a library class to encapsulate some of my logic in my first Android app. One of the functions which I want to encapsulate is a function which queries the address book. As such, it needs a ContentResolver. I'm trying to figure out how to keep the library functions black-boxed... that is, to avoid having each Activity pass in its own context to get a ContentResolver.
Problem is I cannot for the life of me figure out how to get a ContentResolver from within my library function. I can't find an import that contains getContentResolver. Googling said to use getContext to get a Context on which to call getContentResolver, but I can't find an import containing getContext either. Next posts said to use getSystemService to get an object to call getContext. BUT - I can't find any import containing getSystemService either!
So I'm stuck wondering, how can I get a ContentResolver within an encapsulated library function, or am I pretty much stuck having every calling Activity pass in a reference to its own context?
My code is something basically like this:
public final class MyLibrary {
private MyLibrary() { }
// take MyGroupItem as a class representing a projection
// containing information from the address book groups
public static ArrayList<MyGroupItem> getGroups() {
// do work here that would access the contacts
// thus requiring the ContentResolver
}
}
getGroups is the method where I was looking to avoid having to pass in a Context or ContentResolver if I could, as I was hoping to have it cleanly black-boxed.
You can use like this:
getApplicationContext().getContentResolver() with the proper context.
getActivity().getContentResolver() with the proper context.
Have each library function call pass in a ContentResolver... Or extend Application to keep hold of a context and access it statically.
Here is how I wound up doing this, for any who may find this thread in the future:
I used sugarynugs' method of creating a class that extends Application, and then added the appropriate registration in the application manifest file. The code for my application class is then:
import android.app.Application;
import android.content.ContentResolver;
import android.content.Context;
public class CoreLib extends Application {
private static CoreLib me;
public CoreLib() {
me = this;
}
public static Context Context() {
return me;
}
public static ContentResolver ContentResolver() {
return me.getContentResolver();
}
}
Then, to get a ContentResolver in my library class, my function code is such:
public static ArrayList<Group> getGroups(){
ArrayList<Group> rv = new ArrayList<Group>();
ContentResolver cr = CoreLib.ContentResolver();
Cursor c = cr.query(
Groups.CONTENT_SUMMARY_URI,
myProjection,
null,
null,
Groups.TITLE + " ASC"
);
while(c.moveToNext()) {
rv.add(new Group(
c.getInt(0),
c.getString(1),
c.getInt(2),
c.getInt(3),
c.getInt(4))
);
}
return rv;
}
A bit hard without seeing more of how you are coding your library, but I don't see another option then to use the context, and so pass that when calling that class.
A 'random' class does not have the environment to get a contentresolver: you need a context.
Now it's not too strange to actually pass your (activity) context to your class. From http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html
On Android, a Context is used for many operations but mostly to load and
access resources. This is why all the
widgets receive a Context parameter in
their constructor. In a regular
Android application, you usually have
two kinds of Context, Activity and
Application. It's usually the first
one that the developer passes to
classes and methods that need a
Context
(emphasis mine)

How to call method from another class without passing context?

I am currently trying to call a method from a utility class that will reference a new cursor created for this utility method. Unfortunately, my new class will not let me create the cursor without context. I have tried numerous ways of passing context from the calling activity, but get null pointer exceptions in most cases.
Here is the portion of my code:
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Tools.pickRandomItem();
}
});
and in the Tools Class:
public static void pickRandomItem() {
Cursor cur = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null,
null, null,MediaColumns.TITLE + " ASC");
}
Using the above code it throws an error on getContentResolver(), and all attempts I've made to pass context have failed.
I am fairly new to programming for Android, and don't fully understand the concept of contexts. Any help you could provide would be greatly appreciated!
Create a class that extends Application for your project (you have to declare it in the Manifest too), in the Application make a
private static MyApplication app
in the onCreate() of it assign it to the field
app = this;
and make a
public static MyApplication get()
in it. When you need a Context you can use a
MyApplication.get()
A few hints on Context:
Get Context in you View via getContext() and pass it to getContentResolver(context).
Use application-context approach as described here by #apps.
Don't store context inside Activity or Views. This leads to memory leaks.

Categories

Resources