using findviewbyid in a class that does NOT extend Activity in android - android

I have a class that is currently extending Activity and I have methods like findViewById, ArrayAdapter etc.
I want to turn it into an independent class but all the above methods become undefined. What is the problem? Shouldn't importing the classes be enough? For eg, I import android.view.View for findViewById but it still makes no difference.
Please advise.

you should pass the instance of your Activity to your Second Class on the constructor like this :
In your Activity Instanciate your Class like this :
MyClass instance = new MyClass(this);
And in your second Class , the constructor will be like this :
public class MyClass {
public Activity activity;
//.... other attributes
public MyClass( Activity _activity){
this.activity = _activity;
//other initializations...
}
}
and then when you want to use the findViewById() method , you can do like this :
EditText txt = (EditText)this.activity.findViewById(R.id.txt);

if you want to call any function that belongs to Activity then only thing you need to have is context of the Activity.
eg.
class A extends Activity {
Context ctx;
void onCreate(Bundle b)
ctx = this;
B bob = new B(ctx);
}
}
Here is class B.
class B {
B (Activity a) {
a.anyFunctionOfActivity();
}
}

findViewById is non-static public method of the Activity Class ,so it only be available for a Activity object. Therefore, import android.view.View and android.app.Activity won't make it available. To make it available, you could pass around a Actvity object - usually a this point in your activity. However, notice that you should always update your View in the UI thread.

Please try the following:
public static View getLayoutByRes(#LayoutRes int layoutRes,#Nullable ViewGroup viewGroup)
{
final LayoutInflater factory = getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return factory.inflate(layoutRes, viewGroup);
}
TextView tv = (TextView) getLayoutByRes(R.layout.xxx ,Null).findViewById(R.id.editd);

Related

Best approach to access an Activity on the inside of a (custom) view/dialog?

I have only one activity in my app. Before I just stored my views and dialogs static in the activity, so I could access them from anywhere. But I know that this is bad practice because it leads to memory leaks.
So I made them non-static, but now I need to have a reference to my activity deep down in my view hierarchy, to access the views and dialogs stored in the activity.
Example:
My MainActivity has a dialog called a and a custom view called b. How can the onClick method of b show the dialog a?
or in code:
public class MainActivity extends Activity {
private CustomDialog a;
private CustomView b;
#Override
protected void onCreate(Bundle savedInstanceState) {
a = new CustomDialog(this);
b = new CustomView(this);
}
}
public class CustomView extends Button implements OnClickListener {
public CustomView(Context context) {
super(context);
setOnClickListener(this);
}
#Override
public void onClick(View view) {
//wants to show dialog a
MainActivity.a.show(); //Not possible -> a is not static
mainActivity.a.show(); //<-- needs a reference of the activity
// but where from?
}
}
MainActivity mainActivity = (MainActivity) getContext(); won't work because getContext() is not always an activity context.
UPDATE:
I posted an answer below!
For some reasons StackOverflow only lets me accept my own answer in two days
I do not know what exactly your view hierarchy looks like.
I picture your problem for example as:
Activity A has a recyclerview R, now every viewholder H in R should be able to trigger some method in A.
In such a scenario it would be feasable to pass a reference of your activity to your recyclerview adapter and then the adapter passes it to the ViewHolder.
Which then uses it in the onClick method of your (viewholder's) view.
Here, you could use the "callback" pattern. There are many posts about this on stackoverflow, e.g. here.
So the implementation steps would be:
define interface
let your activity implement that interface
let your adapter take the interface as a constructor parameter and pass your activity. (in this example: you have to repeat the step with your viewHolder, pass the interface from the adapter)
use this interfaces method in the onClick method -> this will then trigger your activities method
The implementation depends on the actual hierarchy. If your other view is in a fragment, then you could also use a (shared) ViewModel.
According to your picture I was thinking of the callback-pattern approach first.
You could override onClick in MainActivity; there is probably no need to do it in the class definition itself.
public class MainActivity extends Activity {
private CustomDialog a;
private CustomView b;
#Override
protected void onCreate(Bundle savedInstanceState) {
a = new CustomDialog(this);
b = new CustomView(this);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
a.show();
}
});
}
}
This is a very common pattern in android and I don't know what your view hierarchy looks like but it should work in most cases.
I am having trouble understanding why any class extending Button would need to implement View.OnClickListener. It makes much more sense to create listeners in activities or have MainActivity implement OnClickListener.
A few minutes a go there was an answer here that turned out to be correct.
I don't know why the author deleted it, but it had a link to this answer:
private static Activity unwrap(Context context) {
while (!(context instanceof Activity) && context instanceof ContextWrapper) {
context = ((ContextWrapper) context).getBaseContext();
}
return (Activity) context;
}
So everytime you need the activity you just can call Activity activity = unwrap(getContext());.
I don't know if it is really intended to do it that way or if it is a workaround, but it does its job (atleast in my case).

Why is findViewById undefined in my class?

I have a class and inside the class I try to call the findViewById method but I am getting an error saying findViewById is undefined.
I think I have to pass the WebView to MyClass or something but I have no idea on how to do that.
Here is the code i am working on:
public class MyClass {
Context mContext;
MyClass(Context c) {
mContext = c;
}
...
WebView webview = (WebView) mContext.findViewById(R.id.myWebview);
webview.loadUrl("mysiteUrl");
...
}
public class MainActivity extends Activity {
final myClass mc = new myClass(this);
...
}
I know that this is happening because MyClass does not extend an Activity. However I can get the WebView without extending Activity...
Please help! Thanks.
findViewById is a method that is defined by Android. Therefore you need to actually extend an Android Activity like so for it to recognise it as a method:
public class MyClass extends Activity {
and then import Activity when prompted.
If you want to utilise findViewById in a non-Android Activity then you can specify an Activity for it to find the view in like so:
WebView webview = (WebView) OtherActivity.findViewById(R.id.myWebview);

using "this" to refer the "Context"

I can get the context with methods like getApplicationContext() or getContext() but I am a little confused with using "this" to get the "context" in the following example:
public class GeoActivity extends Activity {
private Button mTrueButton;
private Button mFalseButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_geo);
mFalseButton = (Button) findViewById(R.id.false_button);
mFalseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// another method to get the context
// Context context = getApplicationContext();
Toast.makeText(GeoActivity.this, R.string.incorrect_toast, Toast.LENGTH_SHORT).show();
}
});
}
}
in this code we use GeoActivity.this to refer to the context, but I didn't understand what GeoActivity.this really is and what it is pointing to. also why in this case we cannot use simply this?
An Activity is a Context. If you use "this", it refers to the object in which the "this" appears, so if you use it inside a method of an Activity, it refers to the Activity. Because an Activity is a Context, you can use "this" when you need to pass a Context.
The situation is slightly complicated by the fact that you're using "this" inside the OnClickListener. You're creating an anonymous inner class to use as your OnClickListener. That's fine, but it means that if you just use "this" inside the OnClickListener, inside the Activity, then it'll refer to the OnClickListener rather than to the Activity. If you've got nested classes like this, you can specify which instance you want to refer to by putting the class name in front of the "this". So in your Toast.makeText method, "this" would refer to the OnClickListener that's inside your Activity, but "GeoActivity.this" refers to your Activity.
From Android documentation - Activity extends Context, so you can use Activity when Context is required
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper
↳ android.view.ContextThemeWrapper
↳ android.app.Activity

In Android, is there a more elegant way to retrieve application context inside a inner class?

In Android, is there a more elegant way to retrieve application context inside a inner class rather than passing context as a parameter?
public class MainActivity extends Activity {
class SeekBarChangeListener implements SeekBar.OnSeekBarChangeListener
{
private Context context;
private TextView distanceTextView;
public SeekBarChangeListener(Context context, TextView distanceTextView) {
this.context = context;
this.distanceTextView = distanceTextView;
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Seeing as its an inner class of an Activity, you could use:
this.context = MainActivity.this.getApplicationContext();
call MainActivity.this from the inner class and it will give you the Activity context object.
You should not use the applicationContext i.e. calling getApplicationContext() unless you really need it, but from your example code you have, Activity context should be enough

How to use setContentView(int) from class which does not extend Activity

I need to call the setContentView(int) from my main Activity from another class which does not extends Activity.
In my custom class I've got the private Context context; var that is passed from the Activity in the Constructor but I can't figure out how to acces the Activity methods using the context variable.
If your context is an instance of Activity class, simple class cast should work:
Activity a = (Activity) context;
a.setContentView(R.layout.your_layout);
One solution (may not be the most elegant) is to pass the calling activity to the other class, not just the context.
You would have to pass in a reference to the Activity you're using.
Something like this
class ActivityA extends Activity{
#Override
public void onCreate(Bundle state){
super.onCreate(state);
ClassA myclass = new ClassA(this);
}
}
And then Class A would have:
class ClassA {
public ClassA(Activity yourActivity){
... Get your view here ....
yourActivity.setContentView(view);
... do more things...
}
}

Categories

Resources