here is my class, I want to call a method from DatabaseAccess class:
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder> {
List<Person> mItems;
public Context context;
private static SQLiteDatabase database;
private SQLiteOpenHelper openHelper;
public CardAdapter() {
super();
DatabaseAccess databaseAccess = DatabaseAccess.getInstance(this);
databaseAccess.open();
List<String> kandidatet = DatabaseAccess.getKandidatet();
database.close();
Person p;
mItems = new ArrayList<>();
for (int i = 0; i < kandidatet.size(); i++) {
p = new Person();
p.setName(kandidatet.get(i));
mItems.add(p);
}
.....
....
...
}
the error is in this row:
DatabaseAccess databaseAccess = DatabaseAccess.getInstance(this);
here is the method in the class DatabaseAccess:
private DatabaseAccess(Context context) {
this.openHelper = new DatabaseOpenHelper(context);
}
It doesn't accept "this" as a context
how to fix this?
It's because this must refer to object being of Context class or its child. Activity is subclass of Context your other classes are not. To work around this you can pass context to the adapter object upon its creation:
public CardAdapter(Context context) {
...
DatabaseAccess databaseAccess = DatabaseAccess.getInstance(context);
this refers to the class you're currently in. You must call this from an activity if you want it to be a valid context since activity implements Context interface.
Since you're calling it from a class which does not extend Activity, surely you get an error since this is not a Context in that case. You can fix this by calling the method with the field context you've declared above:
DatabaseAccess databaseAccess = DatabaseAccess.getInstance(context);
Before you do that, you'll need to initialize this field with a proper context, which you can do by changing the constructor to accept the Context :
public CardAdapter(Context ctx){
context = ctx;
//the rest of the code.
Be aware that now you also need to change the call of the constructor to new CardAdapter(this) if you're calling it from the activity (or getActivity if you're calling it from a Fragment).
Related
I'm building a SQlite database for a android quiz app. In Helper class I created a public method getAllQuestions(), but for some reason I can't access this method(or any other method in the helper class) in MainActivity. BTW I imported this class to Main but it doesn't help.
this is the code:
public class DB_Helper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "PRO_QUIZ";
public static final int DATABASE_VERSION = 1;
private SQLiteDatabase db;
public ArrayList<QuestionsDataBase> getAllQuestions() {
ArrayList<QuestionsDataBase> questionsList = new ArrayList<>();
db = getReadableDatabase();
String Projection [] ={
QuestionTable._ID,
QuestionTable.Column_Question,
QuestionTable.Column_Option1,
QuestionTable.Column_Option2,
QuestionTable.Column_Option3,
QuestionTable.Column_Option4,
QuestionTable.Column_Correct_Ans
};
Cursor c = db.query(QuestionTable.Table_Name, Projection, null, null, null, null, null);
if (c.moveToFirst()) {
do {
QuestionsDataBase questions = new QuestionsDataBase();
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Question)));
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option1)));
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option2)));
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option3)));
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option4)));
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Correct_Ans)));
questionsList.add(questions);
} while (c.moveToNext());
}
c.close();
return questionsList;
}
However, when I type in Main: DB_Helper. I cant see any methods.
The method getAllQuestions() is not static. That means that you need an instance of DB_Helper to access that method (you get an instance of an object with the keyword new). So do this:
DB_Helper dbHelper = new DB_Helper();
dbHelper.getAllQuestions();
or alternatively you can declare the method as static this way:
public static ArrayList getAllQuestions(){
...
}
And then access it as you wanted in the first palce:
DB_Helper.getAllQuestions();
But beware that in this case (doing it static) you will also need to declare all class variables used in that method as static too:
private static SQLiteDatabase db;
Recommended further reading: Difference between Static methods and Instance methods
I have a super class:
public abstract class AsyncRequest {
private Context context;
public AsyncRequest(Context context) {
this.context = context;
}
public Context getContext() {
return this.context;
}
protected abstract String getHost();
}
And two sub class:
public abstract class IRequest extends AsyncRequest{
IRequest(Context context) {
super(context);
}
#Override
public String getHost() {
return getHostFromSharedPreferences();
}
private String getHostFromSharedPreferences(){
SharedPreferences preferences = ((Activity) getContext()).getPreferences(Context.MODE_PRIVATE);
return preferences.getString(IPresenter.SP_HOST,"");
}
}
public class LoginRequest extends IRequest{
public LoginRequest(Context context, String name, String password) {
super(context);
}
}
when I init a LoginRequest, and I use getContext() to get the context in IRequest,I get NullPointerException.
I don't know why,do someoneelse know?
Make it sure when you instantiate LoginRequest you are sending non null Context as argument
LoginRequest(Context context, String name, String password)
Class A
{
int x;
A(int x)
{
this.x=x;
}
X getX()
{
return this.x;
}
}
What value are you passing to variable "x" here ?
In your case it is context.
To get the context of a class in android, there is always an inbuilt getApplicationContext() method.
My suggestion is,
Class A
{
Context context;
onCreate Method Block
{
....................
....................
context=getApplicationContext();
}
}
Now use this context variable wherever inside your class, it wouldn't throw null pointer exception.
I just know the casue to problem right now.
As you see,I have init a LoginRequest with the constructor with context,of course the context is null,and the method getContext() in the AsyncRequest I try to invoke using loginRequest.getContex() will get an object which is not null.But the issue is that where I try to invoke the method getContext() is in the IRequest,which means that iRequest.getContext(),but I did't init the iRequest,So this is the cause!.
The problem teachs me that you should know the really object which invokes the method.I simply think that because the LoginRequest extends IRequest,when I init LoginRequest,I init IRequest,which is a bad idea you need to give up.
Because I need to invoke the same code in the Object which extends IRequest,so I invoke the code in IRequest,but I can't get the context in IRequest.There is one of the ways to solve the problem:
I create a class named App and let it extends Application,in this class it has one attribute public static Context context,and in the onCreate method I init the context.Because App is alive in the whole android lifecycle,so I can get it anywhere.Just use App.context.
Finally,Thanks everybody try to solve my problem.
Change this:
public AsyncRequest(Context context) {
this.context = context;
}
...to this:
public AsyncRequest(#NonNull Context context) {
// noinspection ConstantConditions - public API
if(context == null) {
throw new NullPointerException();
}
this.context = context;
}
You'll likely find that you're calling the constructor with a null Context. The constructor is responsible for ensuring that the object's fields are valid, so it's important to check for invalid arguments.
How we can pass data of a methods MainAntivity to another class type SQLiteOpenHelper.
For example we have :(MainActivity.java)
public class MainActivity extends ActionBarActivity {
public static String PACKAGE_NAME;
public String xxx(){
PACKAGE_NAME = getApplicationContext().getPackageName();
return PACKAGE_NAME;
}
}
And another class is :(DB.java)
public class DB extends SQLiteOpenHelper{
MainActivity cc = new MainActivity();
Log.d("test",(String) cc.xxx());
}
But above code not work.
You shouldn't instantiate activity classes this way. Use a separate class instead, where you can define methods which you'd like to use somewhere else. In your case, receiving package name, I'd do something like this
public class PackageNameHelper
{
private Context mContext;
public PackageNameHelper(Context context)
{
mContext = context;
}
public String GetPackageName(){
return mContext.getPackageName();
}
}
Then in your activity / SQLite helper you'd do:
PackageNameHelper helper = new PackageNameHelper(getApplicationContext());
String packageName = helper.getPackageName()
Or you can make the helper class static, that way Context must be passed directly int the getPackageName() method, like
public class PackageNameHelper
{
public static String GetPackageName(Context context){
return context.getPackageName();
}
}
and use it like
//Where context is an instance of a context
String packageName = PackageNameHelper.getPackageName(context);
You should not instantiate your Activities, In your case in my opinion a good way can be defining a constructor for your DB class that takes an argument as context for this application. Than you can save it in a member variable and use it whenever you need.
public class DB extends SQLiteOpenHelper {
Context mContext;
/* Constructor */
public DB(Context context) {
mContext = context;
}
}
If you need to package name within your DB class codes, you can use mContext.getPackageName() to retrieve package name.
is there any way to use in my adapter class.
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
if(!flag){
////
}
// Here i want to set if else condition but i am not able to do this.*/
}
You can use if-else syntax only in methods or constructors. I assume you want to initialize fields of ImageAdapter looking at some parameters. If so, you can do it at the constructor:
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
public String myField;
public ImageAdapter(int mGalleryItemBackground, Context mContext, boolean flag) {
this.mGalleryItemBackground = mGalleryItemBackground;
this.mContext = mContext;
if(!flag){
myField = "abc";
} else {
myField = "cba";
}
}
}
You can do this by following code.
String field = flag?"success":"fail";
In my android project, I have ImageAdapter class in which I pass app context for some further needs.
public class ImageAdapter extends BaseAdapter {
private Context c;
public ImageAdapter(Context c) {
this.c = c;
}
...
}
The problem is that I wanna make ImageAdapter as a singleton to have an easy access to the instance of this class from all of my activities. But I have no idea how to pass app context from getApplicationContext() method from one of my activities to ImageAdapter. So is there any "magic" to do that as follows?
public class ImageAdapter extends BaseAdapter {
private Context c;
private static class Holder {
public static final ImageAdapter IA = new ImageAdapter();
}
private ImageAdapter() {
this.c = /* some magic here */.getApplicationContext();
}
public static ImageAdapter getInstance() {
return Holder.IA;
}
...
}
Maybe you have some other ideas for sharing ImageAdapter for any of my activities.
I'm a newbie to android and I'm a little bit confused with the ways of passing data among activities.
I will be grateful for any help.
Update: 06-Mar-18
Use MyApplication instance instead of Context instance. Application instance is a singleton context instance itself.
public class MyApplication extends Application {
private static MyApplication mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static MyApplication getContext() {
return mContext;
}
}
Previous Answer
You can get the the application context like this:
public class MyApplication extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
public static Context getContext() {
return mContext;
}
}
Then, you can call the application context from the method MyApplication.getContext()
Don't forget to declare the application in your manifest file:
<application
android:name=".MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name" >
I'd rather pass a context instance as a parameter to every method in singleton which really needs it
APPROACH #1:
Since you specify that ImageAdapter is a singleton, one simple answer is to create that singleton from a class that has access to app context:
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
ImageAdapter.createIt(this);
}
}
public class ImageAdapter extends BaseAdapter {
private static ImageAdapter it;
// Get the singleton.
public static ImageAdapter getIt() {
return it;
}
// Call this once, to create the singleton.
public static void createIt(Context context) {
it = new ImageAdapter(context);
}
private final Context c;
private ImageAdapter(Context context) {
c = context;
}
}
APPROACH #2:
If it were not a singleton, then I would use the accepted answer. In that case, remove the local variable from ImageAdapter, because context can always be obtained from MyApplication. Expanding on the accepted answer, if you want a local method as a convenience, define ImageAdapter.getContext(). Complete solution:
public class MyApplication extends Application {
private static Context appContext;
public static Context getContext() {
return appContext;
}
#Override
public void onCreate() {
super.onCreate();
appContext = this;
}
}
public class ImageAdapter extends BaseAdapter {
public ImageAdapter() {
}
// [Optional] Call this whenever you want the app context.
private Context getContext() {
return MyApplication.getContext();
}
}