0

I have a library (aar) that needs a context application because it is using some API methods where a context is needed (WifiManager for example).

I saw there and in many other topics that the common way to achieve this is to pass the Context as a parameter to the object of my lib that needs it. My problem came when reading this article. The lib is to be used by external clients, so I want to avoid all null pointer exception at all cost (you know the rule: if it CAN happen, it WILL happen at some point).

Let's say I have a main entry point in my library, and this class is a Singleton and saves the context (in ctor or via a setter). I would like this class to "host" the Context and behave a little like the Application class: it will provide the context to the other classes of my library.

How can I access this singleton class from the "children" classes or other classes following the principles described in nfrolov's article ?

Let's see some (pseudo) code, with the classes MainSingleton, NetworkManager (singleton too) and DataProvider.

DataProvider can be a member of MainSingleton and doesn't need context, but NetworkManager needs the context to use WIFI_SERVICE and registerReceiver method.

However, DataProvider needs info from NetworkManager, either via registering a listener to it, or getting the data from MainSingleton (that which be used like an event bus to coordinate things between children classes, like we can do with Activities and multiple Fragments).

Case 1

public class MainSingleton
{
    private static MainSingleton instance = new MainSingleton();
    private static Context context = App.getAppContext(); // where the frog do I get that from ?

    ...
}

Problem : as this is the main entry point, I don't have access to "App" in here, so it should be passed as a parameter somewhere, as a setter. But then the context is initialized to null ?

Case 2

public class MainSingleton {
    private static MainSingleton instance = null;

    private Context context;

    private MainSingleton(Context context) {
        this.context = context;
    }

    public synchronized static MainSingleton getInstance(Context context) {
        if (instance == null) {
            instance = new MainSingleton(context.getApplicationContext());
        }

        return instance;
    }
}

Problem: Every "child" instance that need to call the MainSingleton class will need a context too.

Edit

After reading this post: I will most probably consider that my MainEntryPoint is never unloaded when the client application embedding my aar is running, pass the Context as a parameter in an init method and keep that static.

Community
  • 1
  • 1
w00ly
  • 455
  • 1
  • 5
  • 18

1 Answers1

0
public class ConsumerManager {

   private static final ConsumerManager CONSUMER_MANAGER = new ConsumerManager();
   private Context context;

   public ConsumerManager() {
   }

   public static ConsumerManager getConsumerManager() {
       return CONSUMER_MANAGER;
   }

   public synchronized void initialize(Context context) {
       this.context= context;
   }

   public boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting();
   }
}

First you need to call this from activity.

ConsumerManager.getConsumerManager.initialize(this);

To Check network availability from anywhere you just need to call

ConsumerManager.getConsumerManager.isNetworkAvailable();

[EDITED] Do not place Android context classes in static fields (static reference to ConsumerManager which has field activity pointing to Context); this is a memory leak (and also breaks Instant Run)

  • Thank you but that does not solve my problem: The “null static” case. When the client app is in background and Android starts unloading classes, cf the article from nfrolov that I mentioned. – w00ly Mar 02 '17 at 14:53
  • yeah correct, it may have problems when app is in background. Do not place Android context classes in static fields (static reference to ConsumerManager which has field activity pointing to Context); this is a memory leak (and also breaks Instant Run) – OM PRAKASH SEERVI Mar 02 '17 at 15:08
  • Well actually if the context passed is the application context, there is no memory leak, as the library will be unloaded when the Application is, no ? – w00ly Mar 07 '17 at 13:53
  • if you are not running any background task, If an activity is paused or stopped, the system can drop the activity from memory by either asking it to finish, or simply killing its process. if you have some Long running AsyncTask or calling Async Task one after another. What will happen is the task will not get destroyed. lets say one of your task is checking network state, but the activity is already destroyed. In my case i was showing the progress dialog, it was ending up in window leak. – OM PRAKASH SEERVI Mar 08 '17 at 11:43
  • That's why I indicated that the context I am waiting for is the context application :) – w00ly Mar 08 '17 at 13:29