0

I am new to Android (but not to java) and I am confused with Services, ViewModel, Broadcast things and other alternatives used to communicate between Activities. My communication needs are extremely basic.

Consider Midiscope's MainActivity. I want to do something like that, but with the Spinner to select the source on a different Activity. Basically one Activity for the Spinner (call it "SettingsActivity" but obviously cannot be a true Settings for reasons too long for this margin) and another Activity for the UI with the TextView, call it TextViewActivity. I am somewhat able to make it work if I share static variables to access the TextViewActivity from the Settings, so that I can create LoggingReceiver from the Settings but binding it to the TextViewActivity instead of Settings (this). Obviously this is not right (TM), so I attempted all the options I could google to no avail. What it the simplest way to accomplish this?

  • I tried ViewModel and the example in the documentation crashes at MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class);  with error: no suitable constructor found for ViewModelProvider(MyActivity) (yes, I voted 1 star on that documentation page). The "solution" from the accepted answer to a question about it (i.e. using new ViewModelProvider.NewInstanceFactory()) crashes with java.lang.RuntimeException: Cannot create an instance of class com.example.MyViewModel

  • Then I tried IntentService as described at https://developer.android.com/guide/components/services but two things are unclear to me, so perhaps that's not the right approach for my problem:

    1. What should I do in onHandleIntent? My Intent does nothing per se, it should be only a pass-through between whatever comes from MIDI to my UI
    2. How can I access and use the IntentService from both the two Activities described above? Sure, the singleton pattern, but how to make sure I don't create the same problems that sharing a static instance of the Activity causes?
Davide
  • 17,098
  • 11
  • 52
  • 68
  • 1
    "communicate between Activities" -- Google's recommendation is to have few activities and use fragments for different screens. "I tried ViewModel" -- that will not help between activities. "Then I tried IntentService" -- `IntentService` was deprecated a year ago and is not designed for inter-activity communication. It was designed to do a transactional bit of work, such as a network call. "My communication needs are extremely basic" -- could you explain what they are? Is it just passing a parameter from one to another when you start an activity? – CommonsWare Mar 23 '20 at 23:07
  • @CommonsWare Since at least two people think that, I must have not explained myself clearly. Yet I do not know how else to describe it than repeating what I wrote in the question (I am not an English native speaker): "Consider Midiscope's MainActivity. I want to do something like that, but with the Spinner to select the source on a different Activity". – Davide Mar 24 '20 at 13:34
  • 1
    "Consider Midiscope's MainActivity" -- few people will be familiar with this sample app, as it seems fairly specialized (MIDI). Rather than refer to that app, you might want to consider explaining in your own words what you want to do. – CommonsWare Mar 24 '20 at 13:40

2 Answers2

1

If you want to pass some basic data from one activity to another you should use Intent

How to use it:

Activity1 (Sending data to Activity2):

Intent intent = new Intent(context, TextViewActivity.class);
intent.putExtra("EXTRA_SESSION_ID", sessionId);
startActivity(intent);

Activity2 (Receiving data from Activity1):

String sessionId = getIntent().getStringExtra("EXTRA_SESSION_ID");
Biscuit
  • 4,840
  • 4
  • 26
  • 54
  • As I wrote in the question, I was trying to pass an Object (such as the activity itself) not a basic datatype such as a String. – Davide Mar 24 '20 at 13:32
0

The problem is that I was thinking in the "Desktop" mode of developing java (e.g. with Swing) in which the windows are persistent objects, unlike in Android where Activities come and go at all the time.

My solution is to make the LoggingReceiver constructor private and to make LoggingReceiver its own factory with a singleton pattern (i.e. with a getInstance() method returning the sole static instance in existence). Then both the SettingsActivity and the TextViewActivity can access it. The former to do its business of linking the receiver to the right MIDI source, the latter to register itself as the ScopeLogger. Obviously I need also a setScopeLogger() (called by TextViewActivity in its onCreate()) and some null checks in the LoggingReceiver.onSend() if mLogger is not set, since the original code assumed that would happen in the constructor. But this part "business as usual" in java.

Davide
  • 17,098
  • 11
  • 52
  • 68