I have two projects, let's call them App and Dependency.
Dependency is a some kind of GCM parser project that does ... things. It's hard to tell, because it's poorly written, company project that I am forced to use.
Anyways, I'm currently trying to change the part, where I show the notification. I wan't to filter that because sometimes I get notifications that were already showed. My plan is co compare ID's with GreenDAO database... which is implemented inside App. I have singleton class-manager for my database, that manages all database queries.
How should I get to that class from dependency project?
I know, that I should use interfaces, one way or another, but I'm not sure how.
I don't know how your classes are, but in general, you could do something like this:
In Dependency project:
Create a listener for receiving the list you want from the database, let's say onDBRequest:
public interface onDBRequest {
public List<Integer> onIDRequest();
}
Then, in your class where you show he notifications you can do:
public class ClassThatShowsNotifications {
private OnDBRequest mDbListener;
public onDBRequest getDblistener();
public void setDblistener();
...
}
When you need the list of IDs to compare , you can just call:
getDbListener().onIDrequest(); //will return the list of IDs you need to compare
In App project:
Make your DAO implement onDBRequest and implement onIDRequest to return the list you need to compare later:
public class YourDAO implements onDBRequest{
...
public List<Integer> onIDRequest(){
List<Integer> IDs;
//do your stuff to return the IDs
return IDs;
}
}
Now, the only thing you need to do is set the listener you want on the class that shows notifications. Example:
In the YourDAO class
ClassThatShowsNotification notifications = new ClassThatShowsNotifications();
notifications.setDBListener(this);
EDIT
If your class is a based service class, you can do pretty much the same. When you start the service you can can pass your singleton as the listener. You can work with bindService() or make a singleton from your service.
public class YourService extends Service{
private static YourService sInstance;
public static YourService getInstance(){
return sInstance;
}
onCreate(){
sInstance = this;
}
}
Then, when you start the service
YourService.getInstance().setDBListener((onDBRequest)YourDAOSingleton.getInstance());
This would work fine since you have a local service, but you can also take a look at Broadcast Receivers
Related
I'm using Room to implement database, code for working with database is located into Repository, to get instance of database Repository needs Application as class atribute, I want to get instance of Repository in class that extends IntentService and in class that extends Worker class, now, they don't need Application as atribute but to be able to use Repostiory into them I must add it, is this good programming practice? Maybe some other soluction?
public class SunshineSyncIntentService extends IntentService {
private Application mApplication;
public SunshineSyncIntentService(#NotNull Application application) {
super("SunshineSyncIntentService");
mApplication = application;
}
#Override
protected void onHandleIntent(Intent intent) {
SunshineSyncTask.syncWeather(mApplication);
}
}
In this case, is not a bad practice. But I rather use some dependency injection as a more robust solution. You can take a look on Dagger or Koin (for Kotlin).
I've stumpled upon an Android Application Class which implements the Singleton pattern and bind a static object to it.
public class App extends Application
{
public static BigObject myObj;
private static App instance;
public static App getInstance()
{
return instance;
}
#Override
public void onCreate() {
super.onCreate();
instance = this;
myObj = new BigObject(this);
}
}
Are there any problems with this implementation, regarding performance, memory leaks or maybe Exceptions, when getInstance().myObj.something() is called form BroadcastReceiver or Service?
The only drawback I see is somewhat ugly code, using dependency injection would be better. I don't know, but if OS guarantees that all other components will be launched after Application::onCreate than there is no issues. Even non-main threads will not cache value of bigObject. But if you want set value of bigObject after onCreate, or it's creation takes long time you can face issues with data racing or slow startup.
I don't see any problems with this implementation. The Application object is basically a singleton.
In my Android app I have to query some user/session dependent data from a rest webservice. Now I need a way to keep the received webservice results in memory, so that serveral activities/fragments can access them.
I don't want to persist the data (for example a list of the users bank accounts) into a database on the device, because the data expires after a while or when the user logs out.
I also don't want to request the data again and again from webservice, when the user navigates to another activity.
Are there any approved patterns to keep a set of data (some pojo's with more or less properties) in memory during the application is running?
Just for info: I'm experimenting with dagger2, mvp, retrofit2, rxandroid
Regards
Martin
If you already experimenting with Dagger 2, then all you need to do is instantiate a component in Application and use this component in your Activities and Fragments in order to inject a scoped "service".
For example:
Create a class named XyzManager (where Xyz = the actual functionality this manager is responsible for)
Annotate its #Provides method (in Dagger's module) with #Singleton scope
Make sure that the component that injects XyzManager instantiated in Application and add getComponent() method to your custom Appliaction class
In your Activities and Fragments inject XyzManager while using the same component - ((MyApplication)getApplication()).getComponent().inject(this)
If you take the above steps, then all your Activities and Fragments will get a reference to exactly the same instance of XyzManager, and the data you cache in this manager will be accessible everywhere.
The structure you would get is very similar to the structure described in this answer.
Please note that this approach is much better than resolving to static things (e.g. Singleton pattern, or what #KhalidTaha suggested in his answer).
You might want to take a look at my post concerning Dagger 2 scopes if you need a detailed information on that aspect of the framework.
here is a solution:
1- create a DefaultUtil class:
public calss DefaultUtil{
private List<User> listOfUsers;
public static DefaultUtil getInstance(){
if(instance == null)
{
instance = new DefaultUtil();
}
return instance;
}
public List<User> getUserList(){ return listOfUsers; }
public void setUserList(List<User> userList) {
this.listOfUsers = userList ;
}
}
2- when you finish the webservice, call this code:
DefaultUtil.getInstance().setUserList(myWebserviceListOfUsersResult);
and then you can access the list of users from any class by this:
DefaultUtil.getInstance().getUserList();
#Vasiliy
I've studied the linked answer, but I don't get it. I don't use my BankingSession singleton in an activity directly, so calling "getComponent().inject(this).... " won't work. I use the singleton in other service classes (not Android services... just business logic).
// this should be a single instance across the whole app
#Singleton
public class BankingSession {
#Inject
public BankingSession() {
}
}
public class SessionServiceImpl implements SessionService {
private final BankingSession bankingSession;
#Inject
public SessionServiceImpl(BankingSession bankingSession) {
this.bankingSession = bankingSession;
}
}
#Module
public class SessionModule {
#Provides
public SessionService provideSessionService(SessionServiceImpl sessionService) {
return sessionService;
}
}
#Singleton
#Component(modules = {AppModule.class, NetworkModule.class, SessionModule.class})
public interface AppComponent {
Application application();
LoginComponent plus(LoginModule module);
AccountComponent plus(AccountModule module);
BankingSession bankingSession();
}
No matter how I try it, the constructor of BankingSession get's called multiple times
My MainActivity calls another Activity A which needs to access some members of MainActivity.
What is the best way to send a reference to Main Activity (or its context) to Activity A without resorting to complicated methods like parcelables etc?
There are some heavyweight android wrestling matches here but I am not sure that it is relevant to my problem.
details
I have Alert and Alerted objects in a one-to-many relationship (Alerted represents the various times an Alert was rung).
AlertsListActivity extends ListActivity which displays a list of Alert objects from a SQLite database table (primary key: alertId). It has an AlertsListAdapter.
AlertedsListActivity has a ListFragment which displays a list of Alerted objects from Alerted table (foreign key is alertId from Alert table).
It has an AlertedsListAdapter.
AlertsListActivity needs to call AlertedsListActivity to display the list of Alerted objects. I used startActivityForResult().
Inside AlertedsListAdapter
public View getView(int position, View convertView, ViewGroup parent) {
final Alert alertItem = (Alert) mainActivity.alertsListAdapter.getItem(position);
final Alerted alertedItem = (Alerted) getItem(position);
...
I do need the Alert objects also, in order to display some identifying information from them with each Alerted list item. Hence I need the reference to mainActivity.alertsListAdapter
How can AlertedsListActivity access AlertsListActivity?
Update: Since I did not get any solutions, I implemented a workaround. The data that I needed to access from Main Activity, I modified. So the Alert object was made a parcelable, and the SQLOpenHelper was made a singleton.
This allows the data to be accessed from Activity A.
Here's the simple, common way to do it:
singletons typically have variables like the below example, "useThisContext" or "mainFeedIsHere".
public class Cloud
{
private static Cloud ourInstance = new Cloud();
private Cloud() { Utils.Log("cloud singleton launched"); }
public synchronized static Cloud getInstance()
{
return ourInstance;
}
/////////////////////////////////////////////////
public Context useThisContext;
another example ...
public class Feed
{
private static Feed ourInstance = new Feed();
private Feed()
{
Utils.Log("feed singleton launched");
freshestPostsForDisplay = new ArrayList<ParseObject>();
}
public synchronized static Feed getInstance()
{
return ourInstance;
}
public List<ParseObject> freshestPosts;
public MainActivity mainFeedIsHere;
Quite simply when everything launches (or when it changes), those "things" need to set those variables in the singleton. In other words, those things "tell the singleton, where they are." It's that simple.
So, in the MainActivity perhaps, in onCreate, it might say something like...
CLOUD.useThisContext = this;
FEED.mainFeedIsHere = this;
Then for example inside Feed.java you may have say
mainFeedIsHere.feedReload();
It goes without saying you have to check that they are not null (but how else could it be?) and you have to keep them up-to-date as it were. (i.e., for whatever reason you may want to change "useThisContext" -- again how else could it be?)
{Sometimes you'll have one "centralised" singleton .. perhaps "State" .. to sort of combine all these together - so that anyone can "get to" any of those "exposed" things as needed. This is, really, how game engines go; so that you can say more or less SoundEffects.Booms() or Tanks.Faster() or AI.FindVillains() at any time anywhere.}
Cheers!
Since I did not get any solutions, I implemented a workaround. The data that I needed to access from Main Activity, I modified. So the Alert object was made a parcelable, and the SQLOpenHelper was made a singleton.
This allows the data to be accessed from Activity A.
That's probably part one of my question.
Basically I'm struggling with the actual injection for version 1.1.2. I've read the couple of pages on the site, and I feel I'm missing something.
Basically I've done the RoboApplication extension. I've overridden the addApplicationModules method. I've even made a module.
My module looks like this:
public class DataRepository extends AbstractAndroidModule
{
#Override
protected void configure() {
/*
* This tells Guice that whenever it sees a dependency on a TransactionLog,
* it should satisfy the dependency using a DatabaseTransactionLog.
*/
bind(IDataBaseAdapter.class).to(DataBaseAdapter.class);
}
}
In my adapter I have this:
public class DataBaseAdapter implements IDataBaseAdapter
{
private DataBaseHelper _dbHelper;
private SQLiteDatabase _db;
#Inject
protected static Provider<Context> contextProvider;
public DataBaseAdapter()
{
_dbHelper = new DataBaseHelper(contextProvider.get());
}
}
If I don't do there, where is the opportune place for the chunk of code to reside... where I associate injectors?
Finally... my Application has an injection of it like so:
public class MyApplication extends RoboApplication
{
public MyApplication()
{
super();
}
public MyApplication(Context context)
{
super();
attachBaseContext(context);
}
#Override
protected void addApplicationModules(List<Module> modules)
{
modules.add(new DataRepository());
}
#Inject
private IDataBaseAdapter adapter;
public IDataBaseAdapter getAdapter()
{
return adapter;
}
public void setAdapter(IDataBaseAdapter value)
{
adapter = value;
}
...
}
I'm trying to use the Inject attribute as shown. For example:
#Inject
private IDataProvider provider;
A couple of reasons why I'm lost is that I come from a .NET and Flash/ActionScript background plus I've only used StructureMap instead of Ninject (in the .NET world), which I've heard Guice is designed with some of the ideas of Ninject in mind. Could someone help me figure out this small piece?
I'd really like to focus on using 1.1.2 instead of jumping to 2.x of RoboGuice... especially since it is still in beta, so I hope you all don't mind.
Thanks again,
Kelly
Android is quite different from standalone / hosted java application. You do not have main() , but you have certain activity units, which are managed by android framework (activities, services , broadcast receivers)
DI is a technique which allows you to eliminate booler plate code by wiring together
parts in good object oriented way.
As your unit of work is mostly activity, you shall do wiring / creation of your collaborating objects in onCreate() method , and there are dedicated onResume() and onPause() methods (see actviity lifecycle)
Rule of thumb is, does this thing needs to be restarted every time activity loses it focus? If yes, initialize / destroy it in inResume() / onPause(), otherwise - in onCreate()
And if you like to share objects withing entire application ( running in same JVM ) , it is OK to use singleton pattern in android. So you may just have singleton injector factory , and cosult it from everywhere:
InjectorFactory.getInstance(<context if necessary?>).getInstance(whatever you need);
OK, I've figured out what was needed, but I'm not quite sure why after seeing all the information floating out there.
I basically made this change, and now my test passes.
public class DataBaseAdapter implements IDataBaseAdapter
{
private DataBaseHelper _dbHelper;
private SQLiteDatabase _db;
#Inject
public DataBaseAdapter(Provider<Context> contextProvider)
{
_dbHelper = new DataBaseHelper(contextProvider.get());
}
}
While I like using constructors as the tool for injecting, I wonder why it had to work this way, considering that examples I have seen are some kind of reflection class injection.
Anyway, that's this part. Hopefully someone else will find this useful.
Cheers,
Kelly