Not allowed to call my own methods (“static” myste

2019-06-10 03:02发布

问题:

I have a BroadcastReceiver as a separate class file, listening to sensor actions from a service in the background. I want it to show text on the screen on occassions.

I want the BroadcastClass to call a method in my Activity class which takes care of the string to be shown. But my BroadcastReceiver class cannot call methods which are not static(?) "Cannot make a static reference to the non-static method showString(String) from the type myActivity"

And if I make the particular method static in my Activity class, it effectively looses contact with the UI of its own activity by not finding findViewById anymore "Cannot make a static reference to the non-static method findViewById(int) from the type Activity".

In another small app, I had a BroadcastReceiver as an internal class inside an Activity class file. Then I had no problems accessing the UI from it directly. I then had the relevant Views declared as class file fields. But I'd like to structure things better, separating UI from broadcast receiving and analysis. It gets so messy to have the entire application source code in one and the same file.

What does it mean to create instances of an Activity? Should I do that in the Activity itself or in the BroadcastReceiver? I don't want more than one instance of my UI, but I might need to access it from several different classes.

EDIT ADDITION: I try this singleton pattern from a book, but myActivity cannot be instantiated, access to constructor not allowed. Crash before onCreate is entered:

public class MyStartupActivity extends Activity {
    private static MyStartupActivity uniqueInstance;
    private MyStartupActivity() {}
    public static MyStartupActivity instantiate() {
        if (uniqueInstance == null) {
            uniqueInstance = new MyStartupActivity();
        }
        return uniqueInstance;
    }

回答1:

You'll have to add a field for the Activity object in your BroadcastReceiver class, like this:

class MyBroadcastReceiver extends BroadcastReceiver {
    private final Activity activity;

    public MyBroadcastReceiver(Activity activity) {
        this.activity = activity;
    }

    public void onReceive(...) {
        View v = activity.findViewById(ID);
        // ...
    }
}

Initialize it like this

class MyActivity extends Activity {
    public void onCreate(...) {
        MyBroadcastReceiver receiver = new MyBroadcastReceiver(this);
        // ...
    }
}

EDIT: If you don't want to instatiate the receiver every time the Activity is created, you can (for example) introduce a setter to MyBroadcastReceiver:

class MyBroadcastReceiver extends BroadcastReceiver {
    private Activity activity;

    public void setActivity(Activity activity) {
        this.activity = activity;
    }

    public void onReceive(...) {
        if (activity != null) {
            View v = activity.findViewById(ID);
            // ...
        } else {
            // we don't have an activity, do whatever you can do without it...
        }
        // ...
    }
}

and use it in the activity:

class MyActivity extends Activity {
    private static MyBroadcastReceiver receiver;

    public void onCreate(...) {
        if (receiver == null) {
            receiver = new MyBroadcastReceiver();
            // ...
        }
        receiver.setActivity(this);

        // ...
    }
}


回答2:

You need an instance of your class to call that non static function into your static function.


You cannot put the Activity itself as a singelton object. Androud must have access to the constuctor. Better Implement an Application which is something like an singelton object for your app.

You have to declare it into your manifest like this:

<manifest package="your.personal.package">
...
  <application android:label="@string/app_name"
               android:icon="@drawable/icon"
               android:description="@string/desc"
               android:name=".MySingeltonClass"
               android:debuggable="true">
    ...

That into your app you can simply access that application instance by calling getApplicationContext().

Here is a bigger example:

public class MySingeltonClass extends Application {
    public void doSomething() { ... }
}

In any of your activities of your app you can call the function doSomething() via this code:

((MySingeltonClass)getApplicationContext()).doSomething();

Note that your Application class here called MySingeltonClass has its own context so that you can call afik every function that needs a context.