I have my main class that extends Activity and it's over 2k line so I'm trying to write the code in a different class but not sure what it should extend. I've declared a Context and sent it the context from my main class but when I try something like context.findViewById() it won't let me.
What is the best practice here?
public class HomeScreen extends Activity implements OnItemSelectedListener{
//somewhere in a method, in an onClickListener
new Profile(getApplicationContext()).userCreate();
}
public class Profile{
Context ctx;
int userID;
public Profile (Context ctx)
{
this.ctx=ctx;
}
public void userCreate(){
Button create = (Button) ctx.findViewById()// can't call find view
}
}
Related
I know that keyword this refers to current instance of class. But When we implement View.OnClickListener in our class then on calling method textview.setOnClickListener(this), How does argument this(instance object of class) of setOnClickListener(this) call automatically onClick() method. Is there any code in view class which take object and call onClick method on this code or something else is going on?
I want to know what is going behind the scenes, how does android reaches from this keyword to onClick() method? That is what I want to ask?
OnClickListener is an interface in class View.
If your activity implements this interface by setting:
public class MainActivity extends AppCompatActivity implements View.OnClickListener
then you can set a listener for a view like button:
myButton.setOnClickListener(this);
and override the onClick method implementing it like this:
#Override
public void onClick(View v) {
// your code here
}
so a simple explanation is: this means that your view will use your activity's overridden onClick method.
To implement the View.setOnclickListener in your code you need to first implement the public static interface View.OnClickListener.
like this
public class MyActivity extends Activity implements View.OnClickListener {
}
The above interface contains public void abstract method "onClick(View v)" which you override to put your logics
This method is called when a view has been clicked.
for sake of simplicity i have created the code
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// Capture our button from layout
Button button = (Button)findViewById(R.id.corky);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
...
}
here OnclickListener is an interface which have object mCorkyListener
similarly you can use this keyword instead mCorkyListener
‘this’ represents the instance of the current class. You can access the properties and functions of the current class with ‘this’ keyword.
Let's have an interface ElectricityBill
public interface ElectricityBill{
public void pay(int amount);
}
now there are two ways you can pay an electricity bill either by going to nearby electricity board office
ElectricityBill bill = new ElectricityBill(){
#Override
public void pay(int amount){
}
}
payBill(bill);
or by paying the bill online
public class User implements ElectricityBill{
.....
#Override
public void pay(int amount){
}
}
.....
payBill(this);
}
in both the cases, the user has to pay XXX amount, similar is the case if you want to listen to input events you either have to pass the original View.OnClickListener object or implement it and pass this to make it work.
Edit:
when you pass this you tell the current class to handle the click events itself and has to override the onClick() to do so. And when you pass object you let the original class to handle the onClick by creating an anonymouse class and implementing onClick(). but when you pass this your current class get's the authority to listen to input events. It becomes on the type of OnClicklistener and gets the authority to listen onClick()
public class MyClass {
private static MyClass instance = null;
private MyActivity myActivity;
private Button button;
public static MyClass getInstance(){
if (instance == null){
instance = new MyClass();
}
return instance;
}
private MyClass(){};
public void initialize(MyActivity activity){
myActivity = activity;
}
public void releaseMemory(){
instance = null;
}
}
Here in this approach whenver my application exits then
I can release memory by calling releaseMemory() so that myActivity
instance will not be leaked.
public class MyClass {
private static final MyClass instance = new MyClass();
private MyActivity myActivity;
private Button button;
private MyClass(){};
public void initialize(MyActivity activity){
myActivity = activity;
}
public void releaseMemory(){
instance = null; //Can't make it null
//Can do for individual variables
myActivity = null;
button = null;
}
}
In this approach as MyClass instance is final I can't make it null
instead I can make individual variables as null.
So is My understanding correct or am I missing anything respective to memory leaks?
First question, why do you need to keep a reference on an Activity object ?
For most usage you just need a Context object. So if you want to avoid leaking your Activity take the habit to do the following by replacing :
private MyActivity myActivity;
public void initialize(MyActivity activity){
myAcitivity = activity;
}
with:
private Context myContext;
public void initialize(Context context){
myContext = context.getApplicationContext();
}
Since Activity is an implementation of Context, your code should keep working. The method getApplicationContext() will always return an Application Context which you can leak all you want.
Now if an Application Context is not enough and you really need an Activity object (if you need to start other Activity without creating a new task for exemple), first ask yourself why you can't do that in your Activity class directly. If you can't, then maybe you have taken bad decision regarding your code architecture.
If you really need to store Activity object in other object (singleton or not), please remember that activities have a lifecycle, and you need your Activity to notify your MyClass that it will be no longer available (if you don't, and you forget to call releaseMemory(), then your Activity will leak when it goes to background) :
public class MyActivity {
MyClass myClass; // instance initialize somewhere in your code
onPause() {
myClass.setActivity(this);
}
onResume() {
myClass.setActivity(null);
}
}
public class MyClass {
#Nullable Activity myActivity; // tha #Nullable annotation helps you remember to do null checks before using this field.
public void setActivity(Activity activity) {
myActivity = activity;
}
}
In case your MyClass is also a Fragment, you can do the job of setting and releasing your Activity in the methods onAttach() and onDetach() (those methods are automaticaly called by Android, so you don't need to try to call them in your Activity).
Finally, I would advise against your first code sample, because even if you call your method releaseMemory() and ensure you have no reference left in your object A, there is nothing you can do to ensure an object B doesn't still have a reference to your class MyClass.
final field can't be modified. that's why final modifier exists.
second version of your singleton is better regarding conccurency. but it will be never gc'ed until you close the app.
I have a BaseActivity like bellow... Where My Interface global object on super class beame null.
public abstract class BaseActivity extends BaseTabActivity {
//did some implementation
}
public abstract class BaseTabActivity extends BasePickerActivity {
//did some implementation
}
public abstract class BasePickerActivity extends Activity {
// This is an interface
private IOnImagSelected iOnImagSelected;
public void imagePicker(IOnImagSelected iOnImagSelected){
this.iOnImagSelected = iOnImagSelected;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// process data and called iOnImagSelected
// Here I get null point which mean iOnImagSelected is null
iOnImagSelected.onImageSelected(imagepath)
}
}
Now I have a Activity like
public class MyActivity extends BaseActivity implements IOnImagSelected {
public void onPickImageClick(View v){
imagePicker(this);
}
#Override
poublic void onImageSelected(){
}
}
Why My interface variable became null . Please help me with this
I solved it its all hapening because of this option on my Google Nexus 7 developer settings
goto settings->Developer options
in that in APPS category(scroll down to see), see the option
Don't keep Activities (Destroy every Activity as soon as user leabes it).
I found this from this post
That to that guy.:)
You're passing one Activity, MainActivity to the BasePickerActivity but when BasePickerActivity is active MainActivity is null. Basically, your code is invalid; you ought to use Fragments for this sort of thing.
I included the library Swipeable-Cards in my android project. In MainActvitiy.java the onCreate method includes something like that:
SimpleCardStackAdapter adapter = new SimpleCardStackAdapter(this);
//This should also be done on an event in the library class:
adapter.add(new CardModel("Title2", "Description2 goes here", r.getDrawable(R.drawable.picture2)));
Now, in the CardContainer.java (which belongs to the swipeable cards library) there is an event on which I want a new item added to the adapteradapter.add(...). The adapter was defined in the MainActvitiy.java as you can see above.
How can I achieve this?
I first thought about defining a new method in MainActivity and then calling it from my library-class, like that:
public void callfromlibrary() {
adapter.add(...);
}
However then the method and the adapter need to be defined static, additionally I don't know how to make this method of MainActivity available in CardContainer.java.
I believe I need to create kind of a listener to check in the MainActivity what happens in CardContainer.java? I don't know how to do this.
Any help is appreciated!
To allow CardContainer to communicate up to the MainActivity, you define an interface in CardContainer and implement it in MainActivity. When the event occurs in CardContainer, it can then call Interface method in order to add the CardModel to the adapater.
public class CardContainer extends ... {
CardContainerEventListener mCallback;
// Define a interface
public interface CardContainerEventListener {
public void addToAdapter();
}
// Method to register callback
void registerCallback(Activity callback) {
mCallback = (CardContainerEventListener) callback;
}
void someFunction() {
// Event got generated, invoke callback method
mCallback.addToAdapter();
}
}
public class MainActivity extends Activity implements CardContainer.CardContainerEventListener {
// Ensure you register MainActivity with CardContainer, by calling
// cardContainer.registerCallback(this)
public void addToAdapter() {
adapter.add(...);
}
}
please use a Java Interface for achieving this..
declare an interface in the cardcontainer class
public interface yourInterface{
public void callfromlibrary();
}
and intialize the object for calling the function
yourInterface object = (yourInterface) MainActivity;
and implement the interface in your main activity like
Class MainActivity extends activity implements yourInterface
and implement callfromlibrary() method
call this method from cardcontainer class whenever you needed using the object you have created ..
object.callfromlibrary()
This question already has answers here:
Using getResources() in non-activity class
(12 answers)
Closed 8 years ago.
I have come across this question on StackOverflow but I can't use the solutions suggested. One of the most common solutions was to extend the Application class but I can't do that because the class I am in already extends another class. Is there any other way of getting the context of a class?
public class SMSReceiver extends BroadcastReceiver {
.......
.......
CreateDB dc = new CreateDB(mcontext);
dc.addBook(new Book(senderPhoneNumber,ang));
}
Basically, I need to receive a message and add the sender's number and the message to a database and I need to get the context to create an instance of the database. I am a beginner in android so it would be great if you could keep the language simple.
when you extends BroadCastReceiver you have to add this method
public void onReceive(Context context, Intent intent){
}
as you can see there is a context in the parameter
You can get the Context from onReceive() method as follows...
public class SMSReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
CreateDB dc = new CreateDB(context);
dc.addBook(new Book(senderPhoneNumber,ang));
}
}
From Activity in your application you can access the Context of the activity. In your class by using a static reference for example
In you activity class create a static reference
public class MyActivity extends Activity {
public static Context mContext;
public static Context getContext() {
return mContext;
}
public static void setContext(Context mContext) {
this.mContext = mContext;
}
}
and just pass it in your SMSReceiver class like this
public class SMSReceiver extends BroadcastReceiver {
.......
.......
CreateDB dc = new CreateDB(MyActivity.getContext());
dc.addBook(new Book(senderPhoneNumber,ang));
}