I'm really curious about constructors for custom views. Currently I have one which extends the RelativeLayout. Each view need context for initialization. So, I put super() in the constructor. Although, I need the activity in my class so I took context from it. As far as I know, activity is a context too so why Android Studio gives me an inspection that I am missing the constructor with context ? My class looks like this:
public class CustomView extends RelativeLayout {
private Activity activity;
public CustomView(Activity activity) {
super(activity.getApplicationContext());
this.activity = activity;
initialize(activity.getApplicationContext());
}
//initialize method
}
This is the exact message Android Studio gives me:
Custom view CustomView is missing constructor used by tools: (Context) or (Context,AttributeSet) or (Context,AttributeSet,int)
Should I ignore this or should I pass in constructor both: activity and context?
Thanks for all information!
Better pass Context instead of Activity, because its possible to call View with Context but without Activity. For example if you call Dialog from Service.
Also based on documentation there is only one constructor is really necessary. But that constructor has contain AttributeSet as argument.
In your case it should looks like
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
this.activity = (Activity) context; //better to hold context actually
initialize(context);
}
And for sure good practice is to use all available constructors
Related
I have a Widget defined in xml and java. To initialise it, I use:
LayoutInflater.from(getContext()).inflate(...)
which automatically calls the constructor
public Widget(Context context, AttributeSet attrs)
How can I pass more parameters, say, a String, to this constructor?
Create a CustomWidget class that extends the Widget class and create the constructor that receives the same as the super class but also the String you want.
Don't forget to call super(context, attrs);
I'd like to get my string-array without extending Activity in my custom class. Is there a way to do this?
String[] foo_array = getResources().getStringArray(R.array.foo_array); will not work without extending Activity, so I need a work-around.
Pass the context to the constructor of custom class and use the same
new CustomClass(ActivityName.this);
Then
Context mContext;
public CustomClass(Context context)
{
mContext = context;
}
use the context
String[] foo_array = mContext.getResources().getStringArray(R.array.foo_array);
Also keep in mind
Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)
http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html
Also check this
android getResources() from non-Activity class
Edit:
Change this
public class CustomClass(Context context)
{
}
To
public class CustomClass
{
Context mContext;
public CustomClass(Context context) // constructor
{
mContext = context;
}
}
try this,
Context context=getApplicationContext();
String[] foo_array = context.getResources().getStringArray(R.array.foo_array);
And, do not use Activity Context as that is tied to the Activity life cycle.
Update,
getApplicationContext() is from Context class. That means any thing extended Context have this method. This also means you will be able to use this from service or from other resources.
But, if you custom class do not extend Activity/context, you have to pass Context as parameter to use getApplicationContext()
if you declare your activity like this
myMethod(Activity activity) //this is bad
Bud if it is like following,
myMethod(Context context) //this is ok
but from above declaration do not pass Activity or Service Context as they have own life cycle. instead you will use getApplicationContext()
You need pass the Activity context to the Custom class.
private Context context;
public CustomClass(Context context)
{
this.context=context;
}
if you use numberpicker and pass String from sring xml then use this
np_Basic_Hight.setMinValue(0);
np_Basic_Hight.setMaxValue(71);
np_Basic_Hight.setDisplayedValues(getContext().getResources().getStringArray(R.array.hieght));
I have a compound control that needs to access the Application object. My control extends LinearLayout, so because it isn't an Activity I can't call getApplication(). Is there a way I can do this from a Layout/View or pass the Application in?
There are a couple of things you could be depending on what you need the Application object for.
If you need the specific application instance, you could try casting your Context object to an Activity:
public class MyLinearLayout extends LinearLayout {
private Application mApplication;
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
//As this is a custom ViewGroup, Context will be an Activity, but just to make sure..
if(context instanceof Activity)
mApplication = ((Activity) context).getApplication();
else
throw new IllegalArguementException("Context must be an Activity");
}
}
The code above checks to make sure that the Context passed to your custom view is an Activity, but in reality this should always be the case.
If you only need your Application object to use as a `Context', then you can call the 'context.getApplicationContext()' method:
public class MyLinearLayout extends LinearLayout {
private Context mAppContext;
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mAppContext = context.getApplicationContext();
}
}
You have to pass the Context in Constructor when you call My Control Class.
I know this question is general but I am always face to face this problem.
My question is I can reach getResource() or getContext() in Activity but when I want to use a class without activity
example:
public class MapOverlay extends ItemizedOverlay
I can not reach getResources() or Context.
How can I do that anybody know any trick?
I usually do it the following way:
Create a class that extends Application, say MyApp.
Declare a private static Context context field
Declare a (static) getter for the context field
Initialize the field in onCreate(): context = this
Now context is available across all application via MyApp.context()
ItemizedOverlay in not extending android.content.Context.
You can create the construcor like
private Context mContext;
public MapOverlay(Context context){
this.mContext=context;
}
and then use the mContext field to call getResource() or getContext() methods.
Just expose a public method inside your MapOverlay that takes a Context.
public void setContext(Context context) {
mContext = context;
}
So, my first major application is almost coded and I'm doing optimizations on my code. The app works fine, but I'm not sure about my way of passing the context to other classes. I don't want to do it the wrong way. I stumbled upon articles and questions here in Stackoverflow about contexts and which is the right way to pass it to non-activity classes. I read the documentation as well, but being a Finn makes complicated tech speak even harder to understand.
So, a simple question. Is my way of passing my main activity's context to other (helper) classes correct? If not, where can I read more about better practice on these situations.
For example:
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle sis){
super(sis);
new Helper(MyActivity.this).makeMyAppAwesome();
}
}
Helper.java
public class Helper {
Context context;
Helper(Context ctx){
this.context = ctx;
}
public void makeMyAppAwesome(){
makeBaconAndEggsWithMeltedCheese(context);
}
}
Is this OK? It would be nice if someone could provide an easy to read article with examples on this subject.
You can do that using ContextWrapper, as described here.
For example:
public class MyContextWrapper extends ContextWrapper {
public MyContextWrapper(Context base) {
super(base);
}
public void makeMyAppAwesome(){
makeBaconAndEggsWithMeltedCheese(this);
}
}
And call the non activity class like this from an Activity
new MyContextWrapper(this);
It is usually in your best interest to just pass the current context at the moment it is needed. Storing it in a member variable will likely lead to leaked memory, and start causing issues as you build out more Activities and Services in your app.
public void iNeedContext(Context context) {...
Also, in any class that has context, I'd recommend making a member variable for readability and searchability, rather than directly passing or (ClassName.)this. For example in MainActivity.java:
Context mContext = MainActivity.this;
Activity mActivity = MainActivity.this;
I have passed context like this which solved my problem:
public class Utils extends ContextWrapper {
private final Context context;
public Utils(Context context) {
super(context);
this.context = context;
}
public void mymethod(){}
}
super(context); with ContextWrapper helped to make getBaseContext() and getApplicationContext() valid and this.context = context; captured context in variable which I can use wherever needed in methods.
Maybe alternatively you can just opt for using a constructor with this.context = context; and replace all occurrences of getApplicationContext() and getBaseContext().
Well, an even better way is to pass context directly to the method if using only few from a class for avoiding memory leaks.
You could also create a static instance reference to your MainActivity initialized in the onCreate() method
public class MainActivity extends AppCompatActivity {
public static MainActivity mMainActivity;
#Override
private onCreate(Bundle savedInstanceState){
//...
mMainActivity = this;
}
}
and call the context like this:
MainActivity.mMainActivity;
or write a method getInstanceOf() if it's clearer and/or you prefer using an accessor
MainActivity.getInstanceOf();
This strategy might provide you with some flexibility if you decide later that you would like to call an instance method contained in your main activity like so:
MainActivity.mMainActivity.myInstanceMethod();
Just a suggestion. Criticism is welcome and encouraged.