Coming from a non-Java background, I find myself writing a lot of View classes with extensive functionality (in an effort to be portable), that don't necessarily fit nicely into the Android FW setup as far as maintenance - for example, I might have a widget that does something on a interval that I want to stop and clean up when an Activity is paused/stopped/destroyed. Generally I can manage this by just calling a public method on the widget from the containing Activity, but A) sometimes this gets pretty deep, and having to create a public method to access a child in every parent can get ugly, and B) requires extra (uneeded?) attention.
I'm considering using an approach like a global delegate to manage this kind of thing, but have read a lot of warnings about this sort of approach - would something like the class that follows have any inherent flaws that I might be missing?
import java.util.HashMap;
import java.util.HashSet;
public class ActiveRegistry {
private static final ActiveRegistry instance = new ActiveRegistry();
public static ActiveRegistry getInstance(){
return instance;
}
private HashMap<String, HashSet<Runnable>> registry = new HashMap<String, HashSet<Runnable>>();
private ActiveRegistry(){
}
public void register(String key, Runnable runnable){
if(!registry.containsKey(key)){
HashSet<Runnable> list = new HashSet<Runnable>();
registry.put(key, list);
}
HashSet<Runnable> list = registry.get(key);
list.add(runnable);
}
public void execute(String key){
if(registry.containsKey(key)){
HashSet<Runnable> list = registry.get(key);
for(Runnable runnable : list){
runnable.run();
}
}
}
}
Use might be something like...
A View has something that needs to be cleaned up. On instantiation, register it... ActiveRegistry.getInstance().register("paused", someRunnableThatCleansUpStuff)
Extend Activity so that onPause calls ActiveRegistry.getInstance().execute("paused");
You are doing way more work than you need to. Using Fragments (from the support package, if you want to ensure backwards compatibility with older versions of android), will make your life a whole lot easier. Each fragment is embedded in an activity and has a lifecycle that is directly linked with its host activity's lifecycle. Using them should significantly reduce the complexity of your code, as most of what you are currently worrying about will be managed by the system instead.
Related
I have this code that initializes Calligraphy default configuration.
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
// The initialization I want to move
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath("fonts/MyFont.ttf")
.build()
);
}
}
I want to use Dagger 2 in my project but I don't fully understand what classes should I create and where to move this code in order to keep the project clean ?
In short, you probably wouldn't move anything. The problem with this library is that it uses static methods for initialization and utilization. Static methods are a pain when trying to do dependency injection.
The Library (or why you would not change anything)
It looks like this library is 'just' about switching the used fonts by wrapping the context. As such it does not really provide business logic to your project, but just adds to your views / UI.
Injecting a dependency rather than just calling static methods is most useful if you either want to be able to unit test (inject mocks) or easily swap modules / behavior. In the case of globally changing fonts, both seems less likely.
If on the other hand you really need (or want to) be able to test it, or just have a clean design...
...wrap it
Static methods are a pain, because you can not have objects holding the logic. Unless you wrap them. To properly do DI with static methods, you would have to define your own interface.
public interface CalligraphyManager {
/**
* Called on app start up to initialize
*/
void init();
// other methods, like wrapping context for activity
Context wrap(Context context);
}
You now have some manager to access the static methods. The implementation should be fairly simple, since you want to do proper DI the application context and path needed for init() would be passed into the constructor of your implementation. The creation of your manager can thus be handled by your ApplicationModule—just add some provides method
#Singleton
#Provides
// You would also have to provide the path from somewhere or hardcode it
// left as an exercise for the reader
CalligraphyManager provideCalligraphyManager(Context context, String path) {
return new ActualCalligraphyManager(context, path);
}
Your application would then look something like this:
public class MyApplication extends Application {
#Inject
CalligraphyManager mCalligraphy;
#Override
public void onCreate() {
super.onCreate();
mComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
mComponent.inject(this);
// call the initialization
mCalligraphy.init();
}
}
Everything else is as usual. You have a singleton object in your application components graph, you can thus inject the same object into your activities and call `wrap´ where appropriate.
What about testing / mocking?
Since the whole reason of doing this is to make it 'testable', you can now easily provide a mock / stub object.
Create another implementation of the manager where init() would just do nothing, and wrap(Context) would just return the same context—a simple stub object.
I am somewhat new to the OSGi world. And some concepts still elude me.
I'm trying to create a graphical OSGi application using Swing, Equinox and Declarative Services. The goal is to ease the creation of plugins and extensions for the application.
I have stumbled with a design problem and, since I am doing this from the ground up, I want to use all the best practices I can.
I do have a bundle that contains the API and only exposes interfaces to be implemented as services.
public class SomeClass {
}
public interface Manager<T> {
void add(T obj);
void update(T obj);
void remove(T obj);
}
public interface SomeClassManager extends Manager<SomeClass> {
}
public interface Listener<T> {
void added(T obj);
void updated(T obj);
void removed(T obj);
}
public interface SomeClassListener extends Listener<SomeClass> {
}
Let's say I have a bundle (Core) that provides a service that is a manager of certain types of objects (It basically contains an internal List and adds, removes and updates it).
public class SomeClassCoreManager implements SomeClassManager {
private ArrayList<SomeClass> list = new ArrayList<SomeClass>();
private ArrayList<SomeListener> listeners = new ArrayList<SomeListener>();
protected void bindListener(SomeListener listener) {
listeners.add(listener);
}
protected void undindListener(SomeListener listener) {
listeners.remove(listener);
}
public void add(SomeClass obj) {
// Adds the object to the list
// Fires all the listeners with "added(obj)"
}
public void update(SomeClass obj) {
// Updates the object in the list.
// Fires all the listeners with "updated(obj)"
}
public void remove(SomeClass obj) {
// Removes the object from the list.
// Fires all the listeners with "removed(obj)"
}
}
I also have a second bundle (UI) that takes care of the main UI. It should not "care" for the object managing itself, but should be notified when an object is added, removed or changed in order to update a JTree. For that purpose I used a Whiteboard pattern: The UI bundle implements a service that is used by the Core bundle to fire object change events.
public class MainWindow extends JFrame {
private JTree tree = new JTree();
private SomeClassManager manager;
protected void activate() {
// Adds the tree and sets its model and creates the rest of the UI.
}
protected void bindManager(SomeClassManager manager) {
this.manager = manager;
}
protected unbindManager(SomeClassManager manager) {
this.manager = null;
}
}
public class SomeClassUIListener implements SomeClassListener {
public void added(SomeClass obj) {
// Should add the object to the JTree.
}
public void updated(SomeClass obj) {
// Should update the existing object in the JTree.
}
public void removed(SomeClass obj) {
// Should remove the existing object from the JTree.
}
}
My problem here is the following:
The MainWindow is a DS component. I am using its activator to initiate the whole UI. The instance creation is handled by OSGi.
In order to get the updates from the manager, I am exposing the SomeClassUIListener as a Declarative Service. Its instance is also handled by OSGi.
How should I access the instance of the JTree model from the SomeClassUIListener?
I have come up with several options but I am not sure which to use:
Option 1:
Use some kind of internal DI system for the UI bundle (like Guice or Pico) and put it in a class with a static method to get it and use it all over the bundle.
This approach seems to be frowned upon by some.
Option 2:
Inject a reference to the MainWindow (by turning it into a service) in the SomeClassUIListener through OSGi and go from there. Is this possible or advisable? Seems to me that it is the simpler solution. But, on the other hand, wouldn't this clutter the bundle with component config files as the UI got more and more complex?
Option 3:
Create a separate bundle only for listeners and use OSGi to update the MainWindow. This seems to me a bit extreme, as I would have to create an enormous amount of bundles as the UI complexity grows.
Option 4:
Use the MainWindow class to implement the Listener. But, the more services in the main UI bundle, the bigger the MainWindow class would be. I think this would not be a good option.
I cannot think of more options. Is any of the above the way to go? Or is there another option?
Thank you in advance.
Edit:
Just to clarify as Peter Kriens had some doubts about this question.
My goal here is to decouple the user interface from the Manager. By Manager I mean a kind of repository in which I store a certain type of objects (For instance, if you consider the Oracle's JTree tutorial at http://docs.oracle.com/javase/tutorial/uiswing/components/tree.html, the manager would contain instances of Books).
The Manager may be used by any other bundle but, according to my current plan, it would notify any listener registered in it. The listener may be the main UI bundle but may also be any other bundle that chooses to listen for updates.
I am not sure I completely grasp your proposal, and it feels like you are on your way to create a whole load of infrastructure. In OSGi this is generally not necessary, so why not start small and simple.
Your basic model is a manager and an extension. This is the domain model and I would try to flow things around here:
#Component(immediate)
public class ManagerImpl { // No API == immediate
List<Extension> extensions = new CopyOnWriteArrayList<Extension>();
JFrame frame = new JFrame();
#Reference(cardinality=MULTIPLE)
void addExtension( Extension e ) {
addComponent(frame, e.getName(), e.getComponent());
extensions.add(e);
}
void removeExtension( Extension e) {
if ( extensions.remove(e) ) {
removeComponent(frame, e.getName());
}
}
#Component
public class MyFirstExtension implements Extension {
public String getName() { return "My First Extension";}
public Component getComponent() { return new MyFirstExtensionComponent(this); }
}
Isn't this what you're looking for? Be very careful not to create all kinds of listeners, in general you find the events already in the OSGi registry.
Some option here would be to pass the tree model instance as the argument in the listeners methods.
public void added(JTree tree, SomeClass obj)
This way listeners manager would be responsible only for listeners logic, not for the tree state.
Another nice option would be to create a separated TreeProviderService, responsible for holding and serving singleton JTree instance for the application. In such case you would consume TreeProviderService directly from the listeners.
I propose to simply also use DS for the UI creation and wiring. If you use the annotations Peter mentioned you will not clutter your bundles with component descriptors in XML form.
So your listener is a #Component and you inject the UI elements it needs to update into it.
Btw. what you plan to do sounds a bit like databinding to me so you should also investigate what these offer already.
See: Swing data binding frameworks
Btw. you may also want to look for more advanced frameworks than swing. For example some time ago I did a small tutorial for vaadin: https://github.com/cschneider/Karaf-Tutorial/tree/master/vaadin
It already has a databinding for java beans. So this made it really easy for me to code the UI. The full UI is just this little class: https://github.com/cschneider/Karaf-Tutorial/blob/master/vaadin/tasklist-ui-vaadin/src/main/java/net/lr/tutorial/karaf/vaadin/ExampleApplication.java
In the old version I still needed a bridge to run vaadin in OSGi but version 7 should be quite OSGi ready.
I currently have developed an app with some GUI and network operations, but I need to make it more of a library without the GUI.
I know that there is a "is library" option under Properties/Android. But the question is: how to move the GUI elements out of the project to a different app, so that the library/project will have only java code; any suggestion ?
Thanks.
If you are making code into a library, you want to try and decouple it as much as you can from anything else. This makes it much more portable so that more people can use the library how they wish. Even though you are using this library just for yourself right now, later on you may wish to release it to others.
For example, maybe your code is like this currently:
public void computeSum(int a, int b) {
int sum = a + b;
mTextView.setText(String.valueOf(sum));
}
Right now this code is tightly coupled with mTextView. Instead, it makes sense to rewrite the code like this:
//In library
public int computeSum(int a, int b) {
return a+b;
}
and
//Somewhere in your app
mTextView.setText(String.valueOf(computeSum(3,4)));
This is a small change, but you can see that computeSum() is no longer coupled with mTextView. This makes it much easier to use throughout your project and even other projects. Now the computeSum() method is part of an API.
So for your network calls, try to decouple them from your GUI stuff either by using callbacks or return values.
In regards to your latest comment:
You could create a wrapper like so:
public class UIWrapper {
public Runnable runnable;
public SomeUiCallback callback;
}
And then use this in your AsyncTask:
public class YourTask extends AsyncTask<UIWrapper, Void, Void> {
SomeUiCallback mCallback;
protected void doInBackground(UIWrapper... wrapper) {
mCallback = UiWrapper.callback;
UIWrapper.runnable.run();
}
protected void onProgressUpdate() {
}
protected void onPostExecute() {
mCallback.runYourUiStuff();
}
}
I wrote that code quickly so it likely won't compile, but hopefully you get the idea. I think something like this would work, not sure if it's the most elegant solution. You can replace the Runnable with whatever you want to run in the thread.
So both UIWrapper and YourTask would reside in your library. You would create the UIWrapper and then use that in the YourTask.
I'm fairly new to Java. I'm coming from PHP and I used to create registry classes in php using the magic __get and __set methods. So that other parts of the system can easily do:
registry.foo = new Foo();
I should mention I'm trying to create game engine. Here is my registry in Java atm:
class Registry {
private static Map<String, Object> box = new HashMap<String, Object>();
public static Object get(String key) {
if (Registry.box.get(key) != null) {
return Registry.box.get(key);
}else {
return null;
}
}
public static void set(String key, Object o) {
Registry.box.put(key, o);
}
}
Then for the other parts of the system to access the registry, I currently need this whole thing:
((Object) Registry.get("Object")).doSomething();
Which is really a lot of code. In php this would be accomplished by simply:
Registry.foo.doSomething();
Any way to make this a bit more simpler? I guess I could make public fields, but then the regsitry class would need to implicitly create these fields as the possibility of new objects may need to be added which are unknown to the registry class itself, which is.. annoying :P
Thanks in advance!
This is a two pronged problem:
Java is a statically type language, and does not offer in-language flexibility for defining objects at runtime (you can use a library to synthesize classes at runtime, but, see #2)
A global registry for objects defeats a lot of safeties in a type-safe language. If your entire application centers around getting and putting objects into a global Map, there likely safer and less-coupled designs.
How can this be solved?
Redesign your application structure to not need a global map.
Use a dynamic language subset for Java (such as Groovy).
Use Scala 2.10 (JVM compatible) which features a Dynamic type which does exactly what you want.
First of all this method is too verbose:
public static Object get(String key) {
if (Registry.box.get(key) != null) {
return Registry.box.get(key);
}else {
return null;
}
}
It could be just:
public static Object get(String key) {
return Registry.box.get(key);
}
But second, this is definitely a bad design. Global repository - doesn't sound reasonable. A storage of objects of all types by string key - it's terrible.
Any way to make this a bit more simpler?
Not in any practical way. Java is a statically typed language, and the structure of objects has to be known up front. The very idea of an equivalent of PHP's __get and __set is antithetical to the language.
For what it's worth, your "registry" looks like bad design anyway. (Admittedly making some pretty wild assumptions from the little code you've shown.) You shouldn't need a global repository of what appear to be unrelated objects. You should consider some sort of dependency injection instead.
Based on your comment, instead of structuring your code like this:
class World implements GameSystem {
public void update() {
Registry.get("game").doSomething();
}
}
you should do:
class World implements GameSystem {
Game game;
public World(Game game) { // and other dependencies
this.game = game;
}
public void update() {
this.game.doSomething();
}
}
The idea is that components of your program don't really have any business knowing how to find the other components. It also makes dependencies between the components explicit, and helps you avoid circular dependencies.
I've created a few minor apps for Android while learning. Being a PHP developer, it's a challenge to get used to it.
I'm especially wondering how I could define a couple of "general" functions in a separate class. Eg I have a function that checks if network connection is available, and if not, shows a dialog saying that the user should enable it. Currently, that function exists in several of my activities. Of course that seems strange - I suppose it would be more logical to define it once and include it in the activites where needed.
I tried putting it in a new class, and included that class in the original activity. But that failed since eg getBaseContext() is not accepted anymore.
I'm wondering how to go ahead. What should I be Google-ing for ? What is this mechanism called?
You need to create class with static methods. Like this
public class HelperUtils {
public static void checkNetworkConnection(Context ctx) {...}
}
Then you can call it from any place like this:
HelperUtils.checkNetworkConnection(this.getContext());
Assuming current class has Context.
You should read books on general OOP concepts where different type of methods are explained.
You can for example create a class - let's call it NetworkUtils. In this class you can create static method boolean isNetworkConnectionAvailable() and return true if is available and false otherwise. In this class you can create another static method void showNoConnectionDialog(Activity activity) - and in this method you create dialog starting with
public static void showNoConnectionDialog(Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
//setting message, listener etc. and finally
builder.create().show();
}
In your activity, where you want to check and handle network connection you should call:
if (!NetworkUtils.isConnectionAvailable(getApplicationContext())) {
NetworkUtils.showNoConnectionDialog(YourActivityClassName.this)
}
I guess this should work.