简体   繁体   中英

Call method in an activity from another class that extends Application

Hi I am trying to call this method in MainActivity from another class called Startup that extends Application so that it could load each time the app starts:

Can someone show me how to do this? I have read lots of answers but I have not seen any questions that has a class that extends Application yet, I think that caused the issue. All answers that I have seen are about how to call a method from another class that extends Activity:/

this is the method in mainActivity:

 public void showPinLayout() {

        //if initialize in oncreate will cause nullpointer error
        indicatorDots = (IndicatorDots) findViewById(R.id.indicator_dotsMain);
        pinLockView = (PinLockView) findViewById(R.id.pinlockviewMain);
        pinLockView.attachIndicatorDots(indicatorDots);
...
}

this is the Startup class that extends Application and has been initialized in manifest:

<application
        android:name=".Startup" ...>
public class Startup extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        Toast.makeText(this, "Startup", Toast.LENGTH_SHORT).show();

        MainActivity mainActivity = new MainActivity();
        mainActivity.showPinLayout();
    }
}

I would suggest doing something like let the MainActivity start, and in onCreate of the MainActivity call the method in Startup class to initialize some method. the reason is that you don't know at what time the activity will be initialized so wait for it then on Lifecycle Callback initialize some method if needed.

For ex.

public class Startup extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        Toast.makeText(this, "Startup", Toast.LENGTH_SHORT).show();

       
    }

    public void initMain(Context context){
      ((MainActivity)context).showPinLayout();
    }

}

and in MainActivity do something like this.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //just before showing the UI, call the application class method to initialize some method if needed
    ((Startup)getApplicationContext()).initMain(this);
}

Since you cannot new an activity and you should not hold a static reference to an activity to call this method on (since it can lead to leaks), the proper way to access an activity method through app class is through BroadcastReceiver . Here is a simple example:

MainActivity.java

public class MainActivity extends AppCompatActivity {
    public static final String ACTION_SHOW_PIN_LAYOUT = "com.example.package.SHOW_PIN_LAYOUT";

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            showPinLayout();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate();
        ...
        registerReceiver(mReceiver, new IntentFilter(ACTION_SHOW_PIN_LAYOUT));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ...
        unregisterReceiver(mReceiver);
    }
}

Startup.java

public class Startup extends Application {

    ...

    public void callShowPinLayout() {
        sendBroadcast(new Intent(MainActivity.ACTION_SHOW_PIN_LAYOUT));
    }
}

Note that for this to work, MainActivity must be created first, so call callShowPinLayout in a resonable time when you have ensured of your activity creation.

Also I'd suggest EventBus library which is created to ease out these kind of stuff.

Edit:

Since you intend to show a pin lock when user starts the app, you should only deal with activities. I would recommend implementing something like the following: Declaring your pin lock layout as an independent activity. Creating a startup activity (could be a splash screen) and marking it as the launcher activity in AndroidManifest.xml to decide whether to show the pin lock or main activity.

StartupActivity.java

public class StartupActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_startup);

        boolean shouldShowLockScreen = true;  // you can replace this with your own lock screen visibility algorithm
        if (shouldShowLockScreen) {
            // Open LockScreenActivity
            Intent intent = new Intent(this, LockScreenActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        } else {
            // Open MainActivity
            Intent intent = new Intent(this, MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
        finish();
    }
}

AndroidManifest.java

<application
    ...>
    <activity
        android:name=".StartupActivity"
        android:theme="@style/StartupTheme">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
        ...
    </activity>
</application>

With this implementation whenever user enters the app with a cold start, the lock screen algorithm determines if he/she should enter MainActivity or not and if a hot start happens you can easily start your mighty StatupActivity if needed to in onResume() of your MainActivity .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM