Reputation: 419
Will try to keep this as concise as possible...
I would like to have a method in my MainActivty class, say updateUI().
I have another file that is an object called FBManager. That object essentially holds "static" firebase access methods.. let's say signInUser()
From the Activity I call FBManager.signInUser()... It does some logic and moves through 2 private methods and at the last private method, I would like to essentially call MainActivity.updateUI()…
This can't be done as kotlin doesn't have static methods and can't make updateUI() static. MainActivity().updateUI() compiles but is incorrect and don't want to instantiate a new MainActivity. Lastly, I thought of passing the activity into the first constructor like FBManager.signInUser(this)... But after signInUser(), it goes to an override method that can only take a bundle as an optional input (and I don't believe you can put activities into a bundle), thus I can't pass the activity reference to the final private method.....
Edit: Further elaboration
object FBManager {
fun signInUser() {
// Create intent
startActivityForResult(intent)
}
override fun onActivityResult(some intent stuff) {
//Try catch block. In try block call
firebaseAuth(Google account)
}
fun firebaseAuth(acct: GoogleSignInAccount) {
//More logic and an .onCompleteListener
// Inside .onCompeteListener, which is the problem....
MainActivity.updateUI()
}
}
Apologies for layout... Typing on my phone...
-end edit-
I hope all that makes sense as I'm new to programming and find it difficult to explain my problems (since if I truely understood them I could come up with a solution..)
So as per the title, is there any other way to do this... To call a method in MainActivity from an object FBManager?
Upvotes: 1
Views: 7875
Reputation: 507
You can create interface to make interaction between your FBManager and MainActivity. For example:
interface Updatable {
void updateUi();
}
MainActivity:
class MainActivity implements Updatable {
...
@Override
void updateUi()
...
FBManager.signInUser(this)
...
}
FBManager:
object FBManager {
...
void signInUser(Updatable callback) {
...
callback.updateUi()
...
}
}
Upvotes: 0
Reputation:
what about this example? activity
class ExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_example)
FBManager.signInUser {
updateUI()
}
}
private fun updateUI() {
// update UI
}
}
and FBManager object
object FBManager {
fun signInUser(callback: () -> Unit) {
// do work and then
callback()
}
}
Upvotes: 9
Reputation: 7701
and can't make updateUI() static.
True! You want to minimize the usage of static
stuff in any of your activities.
I don't know how good you are at Java, but I use the so called observer-pattern a lot for this kind of problems. You might need to convert it to Kotlin
.
If the MainActivity
is running, it registers to receive events from the FBManager
.
I use the following code from Telegram quite a lot:
public class NotificationCenter {
private static int totalEvents = 1;
public static final int updateActivity = totalEvents++;
private final SparseArray<ArrayList<Object>> observers = new SparseArray<>();
private final SparseArray<ArrayList<Object>> removeAfterBroadcast = new SparseArray<>();
private final SparseArray<ArrayList<Object>> addAfterBroadcast = new SparseArray<>();
private int broadcasting = 0;
public interface NotificationCenterDelegate {
void didReceivedNotification(int id, Object... args);
}
private static volatile NotificationCenter Instance = null;
public static NotificationCenter getInstance() {
NotificationCenter localInstance = Instance;
if (localInstance == null) {
synchronized (NotificationCenter.class) {
localInstance = Instance;
if (localInstance == null) {
Instance = localInstance = new NotificationCenter();
}
}
}
return localInstance;
}
public void postNotificationName(final int id, final Object... args) {
if (Thread.currentThread() == ApplicationLoader.applicationHandler.getLooper().getThread()) {
postNotificationNameInternal(id, args);
} else {
ApplicationLoader.runOnUIThread(new Runnable() {
@Override
public void run() {
postNotificationNameInternal(id, args);
}
});
}
}
private void postNotificationNameInternal(int id, Object... args) {
broadcasting++;
ArrayList<Object> objects = observers.get(id);
if (objects != null && !objects.isEmpty()) {
for (int a = 0; a < objects.size(); a++) {
Object obj = objects.get(a);
((NotificationCenterDelegate) obj).didReceivedNotification(id, args);
}
}
broadcasting--;
if (broadcasting == 0) {
if (removeAfterBroadcast.size() != 0) {
for (int a = 0; a < removeAfterBroadcast.size(); a++) {
int key = removeAfterBroadcast.keyAt(a);
ArrayList<Object> arrayList = removeAfterBroadcast.get(key);
for (int b = 0; b < arrayList.size(); b++) {
removeObserver(arrayList.get(b), key);
}
}
removeAfterBroadcast.clear();
}
if (addAfterBroadcast.size() != 0) {
for (int a = 0; a < addAfterBroadcast.size(); a++) {
int key = addAfterBroadcast.keyAt(a);
ArrayList<Object> arrayList = addAfterBroadcast.get(key);
for (int b = 0; b < arrayList.size(); b++) {
addObserver(arrayList.get(b), key);
}
}
addAfterBroadcast.clear();
}
}
}
public void addObserver(Object observer, int id) {
if (broadcasting != 0) {
ArrayList<Object> arrayList = addAfterBroadcast.get(id);
if (arrayList == null) {
arrayList = new ArrayList<>();
addAfterBroadcast.put(id, arrayList);
}
arrayList.add(observer);
return;
}
ArrayList<Object> objects = observers.get(id);
if (objects == null) {
observers.put(id, (objects = new ArrayList<>()));
}
if (objects.contains(observer)) {
return;
}
objects.add(observer);
}
public void removeObserver(Object observer, int id) {
if (broadcasting != 0) {
ArrayList<Object> arrayList = removeAfterBroadcast.get(id);
if (arrayList == null) {
arrayList = new ArrayList<>();
removeAfterBroadcast.put(id, arrayList);
}
arrayList.add(observer);
return;
}
ArrayList<Object> objects = observers.get(id);
if (objects != null) {
objects.remove(observer);
}
}
}
Then make your MainActivity
look like this:
public class MainActivity implements NotificationCenter.NotificationCenterDelegate {
@Override
public void onPause() {
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateActivity);
super.onPause();
}
@Override
public void onResume() {
NotificationCenter.getInstance().addObserver(this, NotificationCenter.updateActivity);
super.onResume();
}
@Override
public void didReceivedNotification(int id, Object... args) {
if (id == NotificationCenter.updateActivity) {
UpdateUI();
}
}
}
Then in your FBManager
:
NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateActivity, optionalData);
See the other code from this implementation here: https://github.com/gi097/MyWindesheim/tree/master/app/src/main/java/com/giovanniterlingen/windesheim
Upvotes: 0