Android - java set global context to another class - java

The first problem is i have java class with 500 lines. That will so bad, so i want to split them. I found solution in another stackoverflow thread that, we can pass main class context to another class.
//main class
Public class Main{
#Override
Public void onCreate(Bundle inst)
{
Super.onCreate(inst);
ClassB bclass = new ClassB(this);
bclass.setLayout();
}
}
//B class
Public class ClassB{
Activity act1;
Public ClassB(Activity act)
{
act1 = act;
}
Public void setLayout()
{
this.act1.setContentView(R.layout.lay);
}
}
Okay, thats work. But how to make act1 be our main context? so every time i want call setContentView from ClassB i don't need to use act1 again
Edit 1:
What i hope is, i want to make act1 as default context for ClassB. So when i call setContentView from ClassB, its directly called to Main.setContentView
Because if i just call setContentView from ClassB, i wi get NullPointerException. Its make a sense since ClassB have no context

Not sure why you are doing this. There are ways to reduce lines of a single java class instead of keeping UI references in other classes or rendering UI by other classes. You can encapsulate your business logic(Not UI) in other classes which can improve the readability of your code or in your case, if you have multiple Activities which have similar behavior, you can create a base abstract activity class and put all the base code to it.

Related

Why can't i access method from another class but can access variable?

I have two classes named abc and def. Class abc has string named "paths" and function named "test". I can easily use the variable "paths" from another class "def" but can't seem to call the function "test" from class "def".
I have created an object of class abc in class def and tried to call the function but it doesn't work.
public class abc extends Activity {
String paths="path";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
test("lol");
}
public void test(String name){
Toast.makeText(abc.this,name,Toast.LENGTH_LONG).show();
}
}
public class def extends Activity {
abc x= new abc();
String paths=x.paths;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(def.this,paths,Toast.LENGTH_LONG).show();// This is
//working
x.test("hahahas"); // Not working
}
}
i want the method "test" from class abc to be used by class def passing parameter from class def.
The problem is this
abc x= new abc();
You shouldn't be creating an instance of something that extends Activity in this way. You should be using startActivity or startActivityForResult
Also, you shouldn't be holding a reference to one activity inside an instance of another one at all, because activities are created and destroyed by Android so the reference you hold to it may go stale. See Android Activity Lifecycle`. Simply rotating your device is enough to make this happen.
From the tutorial "build your first app" we have start another activity, assuming that you do infact want to launch another activity. You need to learn about intents; let me quote from that link:
An Intent is an object that provides runtime binding between separate components, such as two activities. The Intent represents an app’s "intent to do something."
Thanks for all your comments. I found the solution. In class def, instead of extending Activity i used
public class def extends abc
making class "def" child class of "abc". And after the line
super.onCreate(savedInstanceState);
in class "def" i added one line shown below which did the job.
super.test("lol123");
Are the classes in the same package? (I assumeing that they are in the same package, because you dont have public infront of String paths)
If a method is public you should be able to call it from everywhere.
So i guess you have a problem in your test case.
try with classes, that do not extend Activity and only have the methods needed to test. Then extend your testcase further and further until it stops working.
Is the path variable final?
you might want to add public static final modifier to it.

NullPointerException in super class method's constructor when testing using mockito

I have a super class:
public class A extends Fragment{
public A(Context context){
super(context);
}
}
and class B inherits it:
public class B extends A{
public B(Context context){
super(context);
}
}
In my test class where I'm using Robolectric and Mockito, when I instantiate class B like so: B b = new B(context)
I get a nullpointerexception in class A's constructor's super method. Am I doing something wrong?
Here's the test code:
#Mock Context context;
#Before
public void setup() {
initMocks(this);
B b = new B(context);
}
Simple answer: it isn't that easy.
The exception stack trace which you are hiding from us would tell you/us that those NPE happens within some base Android code. Thing is: you are passing a context object into the Fragment constructor.
Guess what: the Fragment code then starts using that context object. It makes a whole series of calls on that object, in order to retrieve other objects, to then make calls on those objects.
Right now, you only mocked a Context object. Any calls to it that are supposed to return a value will return null by default. Mockito doesn't know anything about the classes you are mocking. So, when you want that a certain call returns something else than null, you have to specify that behavior.
So, the "short" answer is: you have to prepare that mock object to be able to be used like this. The long answer ... was already given; and you need to study its details in depth!
Beyond that; you can have a look into another question dealing with the exact same problem.

How to prevent sublasses from default implementing a method of super class?

I have a method which adds Objects to an static list like this:
#PostConstruct
protected void registerToTransactionList() {
TransactionValidator.registerTransactionList(this);
}
registerTransactionList method just adds "this" to the static list, this method is in BalanceTransactionValidator class which extends TransactionValidator (owner of static list),the problem is all subclasses of BalanceTransactionValidator class are added to static list either,and if I override registerToTransactionList method in them like this:
#Override
#PostConstruct
protected void registerToTransactionList() {
}
It doesn't add subclasses but doesn't add BalanceTransactionValidator either. Can anybody help me on this? Please notice sublasses are overriding this method by default.
make the method private to block the visibility
private void registerToTransactionList() {
}
or make the method final to block it from been override
protected final void registerToTransactionList() {
}
There are two ways of achieving that:
Keep your method as it is; but then you have to actively check for the type of your objects before externally calling that method
Change your whole logic and make that method private
It won't help to make the method final as suggested in one of the comments - your problem is not that subclasses are overwriting that method; in essence, you have a design problem: you wish that subclasses should not invoke that method at all.
So, the only real option that makes sense here is "2.". You see, by having public method on a class that you want to be extended you are implicitly saying: it is perfectly fine to call that method; on any object that is instance of the base class (or child class!).
And in your case, that is not true: you actually do not want that the code behind this method runs for child classes. Then you shouldn't put that method in the list of public/protected methods of your base class!
Finally: you might want to step back and do some reading about good OO design. Class hierarchies do not fall from the sky: you willfully design them for a certain purpose. In other words: there is more to inheritance than just putting some "A extends B" on your class declaration. You have to understand each and every method on your B class; and how your child classes should deal with them!
EDIT: after some more thinking, I guess you are doing things "the wrong way", like:
class BaseClass {
public final void doRegistration() {
BaseClass toRegister = getObjectForRegistration();
if (toRegister != null) { ... register toRegister ...
}
protected BaseClass getObjectForRegistration() {
return null;
}
With that code, you could then put
protected BaseClass getObjectForRegistration() {
if (this instanceof ClassThatShouldBeRegistered) {
return this;
}
return null;
}
into that one class that wants to be registered. Probably there could be even nicer ways of doing so; but after some thinking I don't see how we could avoid the instanceof. But the above code should work; and it only requires specific code only in your base class and in that one class that wants to register something.

Shared variables within subclasses in java

I currently have a parent class which has two subclasses and what I essentially want to do is have them both inherit a shared variable (a float). I need to set the value of the float in subclass1 and then use the value of the float in subclass2. I should add that these are all android activities and that subclass1 is at the beginning of a chain of activities and subclass2 is at the end of this chain, all the activities in between are also children of the same parent class.
What I currently have is something similar to the following:
(I've left a lot of the other code out this is just the bare bones)
class activityParent extends Activity{
public static float value;
public void setValue(){
//grab the value from phone (ill leave this code out and will hardcode a value below as an example)
value = 0.6f;
}
public void useValue(){
//where i use the value in another function here
otherFuncion(value);
}
}
class subclass1 extends activityParent
{
#Override
public void onCreate(Bundle bundle){
setValue();//need this to be initialized first
super.onCreate(bundle);
}
}
class subclass2 extends activityParent{
//some previous code here
//i need to use the value just before the activity finishes
useValue();
finish();
}
That float value is never used anywhere else.
This approach just seems wrong and I know it but I'm not sure how to go about implementing this properly.
I was thinking about passing data with intents but as mentioned the two subclasses arent in direct contact with each other, theres a series of activities between them and I'd rather not have to string this data through them all just to reach the end.
There is FAQ discussed in below link.
How do I pass data between Activities/Services within a single application?
Ideally, since you want to share a primitive data type (a float), Intent is recommended. But since this does not fit well with your requirement, you may skip this.
Next, using "static" (which you are currently doing) is also fine. You can access these static fields from any other class in your application.
But, if you want to have an alternate, then "Singleton" class can be used. This is a class that is designed to have only one instance.
public class Singleton {
private static Singleton INSTANCE ;
private Singleton() {}
public static synchronized Singleton getInstance() {
if(INSTANCE == null){
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
It has a static method with a name such as getInstance() that returns the instance; the first time this method is called, it creates the global instance.
For example activity subclass1 may retrieve the instance and call setValue(0.6); later activity subclass2 may retrieve the instance and call getValue() to retrieve the last set value.
Be very carefull with a cascade of classes. The onCreate() of a SubClass1 calls super.onCreate() which is the onCreate() of ActivityParent. This may trigger a chain reaction (the intent calling ActivityParent is still available to onCreate()).

Call non-static method int static class

I have a inner static class which extends thread inside my main Activity. In this Thread, I need to call a non-static method from my main Activity.
As I see, I have 2 options:
Make my non-static method static: This option would not be feasible cause inside this method I call startActivityForResult and I can't call this in a static way.
Create an object of my main Activity inside the inner static class, and call the method via this object.
MainActivity mActivity = new MainActivity();
//...
mActivity.method();
The one I'm using now is the second, but I have a doubt about it. If I do this, I understand that I'm creating a new instance of MainActivity, and doing this, are all definitions in onCreate method called? Or I'm just calling the method and the variables I'm using inside will be null?
UPDATE --
This is the inner class where I need to call the method from main. I need this to be static because the base functionality of the app needs it to be this way. Now I'm introducing a new method in main activity that must be called when an action happens inside the thread:
private static final class DetectionThread extends Thread {
//...
public DetectionThread(byte[] data, int width, int height) {
}
#Override
public void run() {
//DO STUFF HERE
//Action happens and calls the method from main activity:
SpeechWhenMotion();
//...
}
}
}
And this is the header of the method which is defined in the main activity. Inside of it I'm calling to another method which starts activity for result, so this is the reason why I cannot set this method as static:
public void SpeechWhenMotion() {
//...
}
Assuming MainActivity is the outer class, I guess what you are looking for is
MainActivity.this.startActivityForResult()
Creating another object isn't the right solution.
And BTW, it's equally bad to create a class extending Thread. I don't see a reason you need to do so. For all you need to do unless sophisticated threading, all you need to do is to implement Runnable(). Doing so properly segregate your threading concern from your business logic.
Pass a MainActivity instance to your static method. Then call .method() from that instance.
static void doSomething(MainActivity ma) {
ma.method();
}
This, or the 2nd option that you posted.

Categories