Using #provide and #Inject in the same class - java

I try library cicerone.
The sample use MOXY.
I cant undestend why we should use #ProvidePresenter and #InjectPresenter in the same class, and dont use it anywhere.
#InjectPresenter
StartActivityPresenter presenter;
private Navigator navigator = new SupportAppNavigator(this, -1);
#ProvidePresenter
public StartActivityPresenter createStartActivityPresenter() {
return new StartActivityPresenter(router);
}

#InjectPresenter tells moxy, where should be placed Presenter. #ProvidePresenter tells how to create instance of this Presenter. Also, #ProvidePresenter will be called one time. But presenter field will be initialized after each activity restart.

Related

Vaadin change value from nested Layout

I use Vaadin 14 and would know whether it is possible to report changes in the nested list to objects in the main view.
A rough example is shown in the picture. Above you can see the sum as size (here 2), if I press Delete it should change to 1.
Is that possible and how?
concept
I don't have any code yet, it's a thought where I would like to have a hint about what would be possible, e.g. Observer Pattern or something, but code could look something like this
code:
#Rout("")
public class MainView extends VerticalLayout {
private List<CustomDetails> customDetails = new ArrayList<>();
public MainView(){
final var form = new FormLayout();
customDetails.forEach(form::add);
add(H1("Header"), form)
}
}
public class CustomDetails extends Details{
private CustomForm customForm;
private final Service service;
public CustomDetails(){
customForms = new CustomForm(service.getListOfObjects());
this.setContent(customForms)
}
}
public class CustomForm extend FormLayout{
private FormLayout formLayout = new FormLayout();
private List<Object> objects = new LinkedList<>();
public CustomForm(List<Object> list){
this.objects = list;
setUp();
add(new Paragraph("SUM: "+ list.size()), layout);
}
private void setUp(){
objects.forEarch(o->{
....
layout.add(...)
})
}
}
In Vaadin there is an utility class Binder which is used to bind data to forms. If your use case is related to this, i.e. your so called nested layout is in fact a form and objects you refer to are data beans you want bind into that form. I recommend to study that first.
If you have list editor, I would also investigate if it fits your application to implement it with Grid or IronList/VirtualList, which is backed by DataProvider. Say you edit one item, and after saving the item, you can call dataProvider.refreshItem(item) to update the view.
Observer Pattern or something...
Yes, that is a solution. It is a lot of work and has been done before.
One such library is Beanbag.
Note: I wrote this (or rather, I started writing it a day ago).
EDIT:
As of this edit, we have the ObservableCollection interface. You can use it like so:
// You have a collection called "strings".
// Wrap it in an ObservableCollection.
final ObservableCollection<String, Collection<String>, BasicObservableCollection.Default<String, Collection<String>>> observableStrings = ObservableCollections.observableCollection(strings);
// Add a removed observer.
observableStrings.addElementRemovedObserver(observation -> System.out.println("\"" + observation.getValue() + "\" was removed.");
// Remove an element.
observableStrings.remove("hello");
If you need the wrapper to have List methods, just wait until tomorrow evening EST. I'll have the code up by then and will update this post accordingly.

How to call a method contained in an Android activity?

I have an Activity-class with a method called getPacketNames() that returned the names of some installed packages.
private ArrayList<CharSequence> getPackageNames(){
ArrayList<CharSequence> packageNames = new ArrayList<>();
List<PackageInfo> packagesInfos = getPackageManager().getInstalledPackages(0);
for(PackageInfo packageInfo: packagesInfos){
if(!isSystemApp(packageInfo)){
packageNames.add(packageInfo.packageName);
}
}
return packageNames;
}
I want to make it easy for someone else to call this method from another class. However, in order to do so, they would have to create an instance of the activity. This seems cumbersome, and not correct.
Is thee any way I can create this method outside of an Activity? When I create a separate class and copy-paste the method it does not work, because getPackageManager().getInstalledPackages(0) seems to need to be in an activity.
You should't attempt to do that. Instead create a UtilityClass and make your getPackageNames() as static method.
public final class MyUtils {
public static ArrayList<CharSequence> getPackageNames(final Context context){
ArrayList<CharSequence> packageNames = new ArrayList<>();
List<PackageInfo> packagesInfos = context.getPackageManager().getInstalledPackages(0);
for(PackageInfo packageInfo: packagesInfos){
if(!isSystemApp(packageInfo)){
packageNames.add(packageInfo.packageName);
}
}
return packageNames;
}
private static boolean isSystemApp(...){
...
}
}
Then from the Activity, you can access it as follows:
MyUtils.getPackageNames(this);
Sagar's answer is correct and you should follow that. If you are going to create a util class don't forget to add a private constructor, so that your util class will not be instantiated.
For a "hacky" and bad solution, you can always define your method as public static in your activity class and call it from elsewhere with YourActivity.methodname. But this approach will fail especially if you experiment with Don't Keep Activities option.

how to kill object in org.openide.util.Lookup

I use gephi to draw the social graph.But,it use singleton to create class ProjectController.
#ServiceProvider(service = ProjectController.class)
public class ProjectControllerImpl implements ProjectController {
private enum EventType {
INITIALIZE, SELECT, UNSELECT, CLOSE, DISABLE
};
//Data
private final ProjectsImpl projects = new ProjectsImpl();
private final List<WorkspaceListener> listeners;
private WorkspaceImpl temporaryOpeningWorkspace;
public ProjectControllerImpl() {
//Listeners
listeners = new ArrayList<WorkspaceListener>();
listeners.addAll(Lookup.getDefault().lookupAll(WorkspaceListener.class));
registerNetbeansPropertyEditors();
}
And we can get this class through the netbeans api:
ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
You can see it has a List in this class.When you create a object from this singleton,it will add the list.It make memory leak,I want to kill the object in org.openide.util.Lookup,how can I do?
The code of the ProjectControllerImpl class you linked to also contains a method removeWorkspaceListener(), which you could use to unregister single listeners when they are not needed any more (assuming you know these listeners and that they can be removed).
You could, of course, use your own ProjectController implementation that handles the listeners in a different way:
You could store instances of WeakReference<WorkspaceListener> instead of strong references to WorkspaceListeners if you do not want your ProjectControllerImpl instance to prevent the WorkspaceListeners to be garbage collected. (This implies that a strong reference to each listener needs to be stored somewhere else as long as the listener instance should live.)
Alternatively, do not store the WorkspaceListeners in your ProjectControllerImpl at all, but fetch them via lookupAll() when you actually need them.

GWT-Platform revealing presenters together

Hey so I am just learning the gwtp framework and I have come across a bit of a dilemma. I have a LayoutPresenter at the top level that has a main content slot and menu content slot and I am trying to find a way to bind my presenters for each slot together if possible so when the main content is revealed it will automatically show the correct side menu. Currently I have a static boolean in the Menu's Presenter that get updated onReveal and onHide. I can then check if the menu is visible when the main content is revealed and if not I reveal it.
public class MenuPresenter extends Presenter<MenuPresenter.MyView, MenuPresenter.MyProxy> {
private static boolean hidden = true;
...
#Override
protected void revealInParent() {
RevealContentEvent.fire(this, LayoutPresenter.SIDE, this);
}
#Override
protected void onReveal(){
super.onReveal();
hidden = false;
}
#Override
protected void onHide(){
super.onHide();
hidden = true;
}
public static boolean isHidden(){
return hidden;
}
}
Then in The main content Presenter:
public class ContentPresenter extends
Presenter<ContentPresenter.MyView, ContentPresenter.MyProxy> {
...
private final DispatchAsync dispather;
private final PlaceManager placeManager;
#Inject
public PhoneCallPresenter(final EventBus eventBus, final MyView view, final MyProxy proxy, final DispatchAsync dispatcher, final PlaceManager placeManager) {
super(eventBus, view, proxy);
this.dispather = dispatcher;
this.placeManager = placeManager;
}
#Override
protected void revealInParent() {
RevealContentEvent.fire(this, LayoutPresenter.CONTENT, this);
}
#Override
protected void onReveal() {
super.onReveal();
if (MenuPresenter.isHidden()){
placeManager.revealPlace(new PlaceRequest(NameTokens.menu));
}
}
}
As far as I understood the question, you want to have different side-menus for different main contents.
In this case there are two solutions:
Treat the menu as a normal Presenter (you will probably have multiple of them for each main content type). You just need to annotate the corresponding MenuPresenter with the same history token as your main content Presenter. So for the above example you would have a PhoneCallMenuPresenter that is annotated with the same history token as your PhoneCallPresenter. When you navigate to /phonecall (or whatever your history token is), both PhoneCallPresenter and PhoneCallMenuPresenter will be revealed automatically . (you don't have to do anything).
In case you want to have only one MenuPresenter and put the logic what to display in the Presenter itself, I would recommend to use a PresenterWidget instead of a normal Presenter. The MenuPresenterWidget will be injected into the LayoutPresenter and will be added to the LayoutPresenter.SIDE slot. You can define a setter for the MenuPresenterWidget to specify which main content is currently displayed (the setter will be called from the LayoutPresenter or you can override the onReset() method and check the current place request and decide what to display in the menu.
For solution 1 you have to have one MenuPresenter for each main content Presenter and potentially many code lines will be redundant (you could create a base MenuPresenter and derive from it). So in case you have a lot of business logic in the side-menu which is quite different from main content to main content, I would go with solution 1. In case you only display different links the overhead of creating a MenuPresenter per main content Presenter might be to high and I would go with solution 2 and create only one MenuPresenterWidget for all main content types and always show it.

Singleton in GWT project

Could some explain me something. Here is some scenario.
Let assume i have a class template and use Gin/Guice in the app.
#Singleton
public class Template extends Compose
{
private HorizontalPanel header;
private HorizontalPanel content;
private VerticalPanel menu;
public Template()
{
this.add(initHeader());
this.add(initMenu());
this.add(initContent());
}
public void setContent(Widget widget)
{
content.clear();
content.add(widget);
}
.............
......
}
and in the entry class
........
public void onModuleLoad()
{
RootPanel.get().add(new Template());
....
}
Every time i need to reload the content i do..
For example
HorizontalPanel hp = new HorizontalPanel();
hp.add ....
...
Template template = injector.getTemplate(); // return singleton instance using gin
template.setContent(hp)
and so on..
So, Template is singleton and as far as i know singleton instance is one per VM meaning shared by entire application, right?
Template class has header, menu and content, the idea is to reload only the content part as cleaning and adding widgets.
But is this a good approach?
For example, could we have a situation like user "A" setContent(widgetA) ,but in the same time user "B" use method setContent(widgetB) ,so what is going to happen here?
Thanks, if anyone could share with me a good approach eventually and comment that one.
Regards
#Singleton is scoped to the Ginjector instance (yes, if you GWT.create() your GInjector twice, you'll get two "singletons"). There's no single mean GIN can somehow "intercept" your new Template() in onModuleLoad, so injector.getTemplate() will return a distinct template instance.
(this is totally different from the "singleton code anti-pattern" that Stein talks about, using static state)
There's no magic: GIN is a code generator, it only writes code that you could have typed by hand.
As for your other questions:
You client code obviously run on the client, i.e. on the browser. There's one "application instance" per browser tab/window displaying your app. There's no "user A" and "user B" at the same time.
JavaScript is single-threaded, so you don't have to fear for concurrent accesses either.
I have injected the class with common RPC code for our app.
Here's how:
#Singleton
public class SomeService {
/** The real service. */
private static final RealServiceAsync realService;
...
}
Our Gin module:
public class MyGinModule extends AbstractGinModule {
#Override
protected void configure() {
bind( SomeService .class ).in(Singleton.class);
...
...
}
}
And it's injected as singleton as follows:
public class ApplicationInfoPresenter {
#Inject
private SomeService service;
...
...
}
I'm pretty sure the annotation is ignored by the GWT compiler.
When I need a Singleton in gwt i just create a class with a private/protected constructor, and a private static NameOfSingletonClass instance; and a getInstance() method that initializes the instance if null and returns the instance.

Categories