I (having mediocre developing skills) actually try to use Sugar as a database wrapper for my android project.
Therefore, I was following along the "Getting-Started-Guide" (http://satyan.github.io/sugar/getting-started.html) to get ready as soon as possible.
I created a class for my entities, called DataSet.java :
import com.orm.SugarRecord;
public class DataSet extends SugarRecord{
int someData;
double evenMoreData;
public DataSet(Context ctx){
super(ctx);
}
public DataSet(Context ctx,
int someData,
long evenMoreData) {
super(ctx);
this.someData = someData;
this.evenMoreData = evenMoreData;
}
}
I call the class in the following way:
someGreatClass something;
someMoreGreatCode somemore;
DataSet dataSet = new DataSet(
ctx, // Here Eclipse throws the error
something.method(),
somemore.anothermethod());
DataSet.save();
When I try to build this and to push it onto my device, Eclipse refuses to compile and throws this error:
ctx cannot be resolved to a variable
Considering the fact that I'm relatively new to Android development, the error may be obvious and I hope to get a tip how to solve this.
P.S.: Furthermore, I don't fully get the developer's statement in the getting-started-Note:
Please retain one constructor with Context argument. (This constraint will be removed in subsequent release.)
Thank you very much!
// Edit: Did edit the class name from LocationDataSet to Data set for clarification
First of all, the getting-started-note tells you that you need a constructor with only a context parameter, you did this here so that's ok
public DataSet(Context ctx){
super(ctx);
}
about
ctx cannot be resolved to a variable
I think you don't have a variable called ctx, I don't know if you're familiar with android context? (basically a context is a service or an activity), if you're using this code in an activity or a service, just use the 'this' keyword and not the ctx variable
The code you provide doesn't really show what you're doing, but you showed us the code from 'DataSet', but the error happens with a LocationDataSet? And you're calling save on DataSet?
The save method must be called on an object, not a class.
Also don't forget that sugar needs the special application class in the manifest
UPDATE with example:
Your dataset class (the sugarrecord) should look like this, that's ok in your code as far as I can see
public class DataSet extends SugarRecord<DataSet>{
private String someData;
public DataSet(Context c){
super(c);
}
public DataSet(Context c, String someData){
super(c);
this.someData = someData;
}
}
An activity that uses the record should look like this
public class SomeActivity extends Activity {
public void someMethodThatUsesDataSet(){
// Create a dataset object with some data you want the save and a context
// The context we use here is 'this', this is the current instance of SomeActivity,
// you absolutely need this, I think this is what you're doing wrong,
// you can't use ctx here because that's not a known variable at this point
DataSet example = new DataSet(this, "data you want to save");
// Tell Sugar to save this record in the database
example.save();
}
}
Related
I am really new to Android development. In my app, I perform different async task and needed to save the result from those task to the database which requires context. Inspired from this answer I started using context in all my classes as a member variable. This seemed like a good method, but now ALL my background task and other classes which deal with preference have context as a member variable.
Code example -
public class Task extends AsyncTask<Void, Void, String> {
Context context;
public Task(Context context){
super();
this.context = context;
}
protected String doInBackground() {
//myAsyncTask
..
}
..
protected void onPostExecute(String response) { //response from the request
DbHelper helper = new DbHelper(context);
//save to db
}
I have about 3 or more of such tasks running consecutively at times. So whenever I need to do a background task, I first have to initialize the async task with the context and then initialize the DbHelper using that context. I feel like I'm doing it all wrong. This doesn't seem like a good method to me now (may lead to huge memory leaks imo). Plus it feels like duplication and that I can have access to the context in a better way.
Is it recommended to use context like this? Or does it actually have a disadvantage and I'm better off using some other method? Something like
public class MyApplication extends Application {
private static Context context;
public void onCreate(){
super.onCreate();
MyApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApplication.context;
//use context as MyApplication.getAppContext();
}
}
Which one is better to use?
Neither is correct. Do NOT maintain a reference to Context anywhere, it gives memory leaks because then the VM cannot garbage-collect the Context. We also tried several solutions but all failed. There's no other solution than pass the Context whenever you need it (if you look at the Android API you will see that it also works this way, and it's for a reason).
Problem using Application
I'm rewriting an app (first 'version' had little-to-nothing in terms of analysis and it ended up piling a bunch of problems I wanted to get rid of) and I'm bumping my head against a problem that never showed up in the first version.
Thing is: I have a Class for geographical data. It just supplies String arrays that I can tuck into spinners adapters. Since I used a values xml file, the class needs access to Context to get the proper resources.
Since I use this geographical data in several points of the app, I thought I could create a Class to extend Application and, in onCreate, instantiate the Geography Class, I thought it would be more efficient to load it just once and use it as many times as I wanted. This worked on my first version:
This is MyApplication class
private static Context context;
public void onCreate(){
super.onCreate();
MyApplication.context = getApplicationContext();
geografiaEspana = GeographyClass.getInstance(context);
}
public static GeographyClass getGeografiaEspana() {
if(ctx==null){
Log.w("TAPABOOK", "Tapabook.context nulo");
}
if (geografiaEspana==null){
Log.w("TAPABOOK", "Tapabook.geografiaEspana nula, instanciando");
geografiaEspana = GeographyClass.getInstance(ctx);
}
Log.i("TAPABOOK", "Tapabook.geografiaEspana instanciada");
return geografiaEspana;
}
And this is my GeographyClass
private static GeographyClass instance = null;
public static GeographySpain getInstance(Context context){
if(instance== null){
instance = new GeographySpain(context);
}
return instance;
}
public GeographySpain(Context context){
Resources res = context.getResources();
// load resources data
}
This worked, as I said, ok in my first version. However, in my new version I'm getting a NullPointerException on this line "Resources res = context.getResources();" I've checked and it turns out that the context I'm supplying it's null... And I don't get to understand why or what I'm doing wrong
Ok, I solved it (I'd swear I already commented on this, but since it's gone...).
Thing is, I'm not used to use Application classes and I had forgotten to declare MyApplication in the Manifest file. Noob mistake. As soon as I declared it, the app ran OK
DBHelper db =new DBHelper(context);
Cursor result = db.weeklyMedicinesTaken();
//WeeklyMedicinesTaken is a function in DBHelper class which returns cursor containing an integer value.
startManagingCursor(result); //this function is a resistance in what i want to do.
while(result.moveToNext())
{
int count=result.getInt(0);
}
result.close();
Actually I have simple classes (non activity classes) in which i want to retrieve data from sqlite and apply some processing and evaluation of data., but the problem is that the code above is working fine in activity but not working in any non activity class or in any static function of activity so that i can call that function from any class.
Any Suggestion Please??
Use getActivity().startManagingCursor(c) or pass an instance of your context to the class inwhich you want to call startManagingCursor()
Lets say your class is sth like this:
Person{
Context mContext;
String name, surname;
Person (Context context){
mContext = context;
}
While creating your Person object you should pass the context like this:
in your onCreate() or somewhere else inside the activity:
Person p = new Person(getActivity());
However, it's not a good practice to manage your cursor outside the activity.
You can examine this tutorial for simple patterns.
I am trying to send the events from one Java class to Activity.
Scenario is, Will be having some data in the native, native will call the callback function which is in java code, This class processes data, after the processing i need to update the UI. I want to update the UI at one place in the Activity handler. (Dont want to use runOnUiThread() everywhere).
I was not able to send the events properly with the below approaches.
1st Approach:
1) Define functions for posting messages in to the queue and call these functions.
2) To call the above mentioned functions (point 1) we need context, if i maintain the static variable for maintaining the context and returning it, if the activity is created twice we wont able to get the write context for the first activity.
public class Activity1 {
protected static Context myContext = null;
protected Handler myHandler = null;
#override
public void onCreate() {
myContext = this;
myHandler = new Handler();
}
public static Context getMyContext() {
return myContext;
}
public void postEvent1() {
myHandler.sendMessage();
}
}
2nd Approach:
1) Making the handler as a static variable and returning this with the help of static function. - Not a good design to expose the internal variables.
2) Cons will be like above, when a second activity is created.
public class Activity1 {
protected static Handler myHandler = null;
#override
public void onCreate() {
myHandler = new Handler();
}
public static Context getMyHandler() {
return myHandler;
}
}
Is it possible to get the activity context without using the static variables and static functions?
Please share the knowledge if anyone knows. :)
Thanks & Regards,
SSuman185
I used a container class HashMap for storing the contexts with the key.
I used the name of the class as the key.
When the second activity is trying to register with class containing hashmap, it will reply with context of the already stored activity (null if not).
So like this I am able to store the contexts' of the classes and avoid loosing of the first activity context if I am creating the second one.
Please add if any one gets better solution.
I want to use a singleton pattern to hold a database and some other data/methods for my Android application.
I realize there are many reasons against singletons, but for this case I'd like to use it.
I've sub-classed UIApplication and made a data class within it called MyAppData.
MyAppData needs to have access to the SQLite database.
When I create the databse, I need to pass a context. I could pass the application context, but it will not directly relate to MyAppData.
I don't know if this wlll cause problems with my code.
So my thought is to have MyAppdata extend android.content.ContextWrapper. I don't think I should extend Activity because it's really not an activity, its a data class with methods to access the database.
I'm wondering if I extend ContextWrapper will there be something deep in the code I'm missing that will cause big problems down the road (memory leaks, etc).
This may not be the ideal approach to this (and I've considered other options), but my goal is to:
Have a singleton class in UIApplication that can encapsulate the database and be retrieved easily from any activity in my app.
Thanks in advance for your suggestions/warnings/advice.
Subclass android.database.sqlite.SQLiteOpenHelper and android.app.Application (with the latter being properly declared in AndroidManifest.xml).
Now,
public class MyApplication extends Application {
private static SQLiteOpenHelper openHelper;
#Override
public void onCreate() {
super.onCreate();
openHelper = new DbManager(this);
//
}
public static SQLiteDatabase getDB() {
return openHelper.getWritableDatabase();
}
}
Then have helper DAO classes that will perform instertions/updates/etc.
That's what I'm using in all of my apps.
I've used this approach:
Create a class responsible for managing the db, let's call it DBUtil. This class will extend android.database.sqlite.SQLiteOpenHelper. You can pass a reference to the application context to the constructor of this class. This class will contain methods for creating the db, adding, removing and retrieving items.
Create another class, let's call it AppCore, create a static instance of the DBUtil and a static init() method that accepts an ApplicationContext object
public class AppCore
{
public static var dbUtil:DBUtil;
public static void init( ApplicationContext context )
{
dbUtil = new DBUtil( context );
}
}
Then in the onCreate() method of our your application's main Activity, initialize the AppCore class.
#Override
protected void onCreate(Bundle savedInstanceState)
{
AppCore.init( getApplicationContext() );
}
So, it's not really a Singleton. Instead, the DBUtil instance is maintained as a static property, yet still accessible throughout your application, such as this:
AppCore.dbUtil.createNewRecord( params );
Also, I found this tutorial to be very helpful when getting started with this topic: http://developer.android.com/guide/tutorials/notepad/index.html