48

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.

Houcine
  • 24,001
  • 13
  • 56
  • 83
Namratha
  • 16,630
  • 27
  • 90
  • 125

4 Answers4

86

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);
Houcine
  • 24,001
  • 13
  • 56
  • 83
  • 1
    This does not work. findViewById can only be called on Activity and not on Context. I tried your approach but it still gave me errors. – Namratha Dec 02 '11 at 04:48
  • 3
    So see my edit, just pass the instance of the Activity intstead of the Context :) – Houcine Dec 02 '11 at 10:25
  • Ok, I did that :) When I call findViewById on the Activity object, the Listiew that I'm trying to find is NULL. Is that because I haven't used setContentView for the XML file that contains the ListView, before? – Namratha Dec 05 '11 at 07:03
  • Yes setContentView was missing and that was that problem. setContentView can be called on the Activity object. – Namratha Dec 05 '11 at 07:10
  • yes that's it , when you override the method onCreate , you should always set the contentView BEFORE ANY call of the method findViewById() :) – Houcine Dec 05 '11 at 10:09
  • @Houcine what should be done to make this work in AsyncTask as it doesn't work in this case? – Himanshu Aggarwal Apr 21 '15 at 17:42
  • you can create your own asynctask class wich extends from the asyncTask class. and then define a constructor to your class which takes the Activity context as parameter – Houcine Apr 21 '15 at 20:39
  • 1
    The "problem" with this approach is that if you also need a reference from the activity to the class, it will create a circular dependency. Java can handle it, but not so sure if you would consider this a good practise. It introduces a risk for a memory leak here. For my use case I worked my way around it by re-defining my view inheritance hierarchy that fits the needs of my app. – html_programmer Mar 28 '17 at 08:04
  • Don't forget that it's often a bad idea to give away your activity. You make yourself open to bad encapsulation and memory leaks. Preferrably use a WeakReference – avalancha Aug 07 '18 at 13:28
  • After I tried this, I was wondering why some data will not be stored to my firebase database anymore. I debugged at another point where it still worked. I was confused when I saw that Android Studio stopped at the breakpoints before storing the data, but firebase showed that the data was stored. At other points, it was not working anymore. I fixed this bug by deinstall the app once. I would not recommend this solution. – RuhrpottDev Jul 27 '22 at 20:53
11

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();
    }
}
BoJack Horseman
  • 4,406
  • 13
  • 38
  • 70
N-JOY
  • 10,344
  • 7
  • 51
  • 69
6

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.

pierrotlefou
  • 39,805
  • 37
  • 135
  • 175
  • Ok i understand why it's not available but isn't findViewById a method of the View class? Also could you explain why we should always update our View in the UI thread(are you referring to the main Activity?)? – Namratha Nov 30 '11 at 11:38
0

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);
Koby Douek
  • 16,156
  • 19
  • 74
  • 103
Ali Bagheri
  • 3,068
  • 27
  • 28