This repository was archived by the owner on Oct 25, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 152
Expand file tree
/
Copy pathPresenter.java
More file actions
147 lines (127 loc) · 4.8 KB
/
Presenter.java
File metadata and controls
147 lines (127 loc) · 4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* Copyright 2013 Square Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mortar;
import android.os.Bundle;
import mortar.bundler.BundleService;
import mortar.bundler.Bundler;
public abstract class Presenter<V> {
private V view = null;
/** Load has been called for the current {@link #view}. */
private boolean loaded;
private Bundler registration = new Bundler() {
@Override public String getMortarBundleKey() {
return Presenter.this.getMortarBundleKey();
}
@Override public void onLoad(Bundle savedInstanceState) {
if (hasView() && !loaded) {
loaded = true;
Presenter.this.onLoad(savedInstanceState);
}
}
@Override public void onSave(Bundle outState) {
Presenter.this.onSave(outState);
}
@Override public void onEnterScope(MortarScope scope) {
Presenter.this.onEnterScope(scope);
}
@Override public void onExitScope() {
Presenter.this.onExitScope();
}
};
/**
* Called to give this presenter control of a view, typically from
* {@link android.view.View#onAttachedToWindow()}. Sets the
* view that will be returned from {@link #getView()}.
* <p/>
* This presenter will be immediately {@link BundleService#register registered}
* (or re-registered) with the given view's scope, leading to an immediate call to {@link
* #onLoad}.
* <p/>
* It is expected that {@link #dropView(Object)} will be called with the same argument when the
* view is no longer active, e.g. from {@link android.view.View#onDetachedFromWindow()}.
*
* @see BundleService#register
*/
public final void takeView(V view) {
if (view == null) throw new NullPointerException("new view must not be null");
if (this.view != view) {
if (this.view != null) dropView(this.view);
this.view = view;
extractBundleService(view).register(registration);
}
}
/**
* Called to surrender control of this view, e.g. when the view is detached. If and only if
* the given view matches the last passed to {@link #takeView}, the reference to the view is
* cleared.
* <p/>
* Mismatched views are a no-op, not an error. This is to provide protection in the
* not uncommon case that dropView and takeView are called out of order. For example, an
* activity's views are typically inflated in {@link
* android.app.Activity#onCreate}, but are only detached some time after {@link
* android.app.Activity#onDestroy() onExitScope}. It's possible for a view from one activity
* to be detached well after the window for the next activity has its views inflated—that
* is, after the next activity's onResume call.
*/
public void dropView(V view) {
if (view == null) throw new NullPointerException("dropped view must not be null");
if (view == this.view) {
loaded = false;
this.view = null;
}
}
protected String getMortarBundleKey() {
return getClass().getName();
}
/** Called by {@link #takeView}. Given a view instance, return its {@link MortarScope}. */
protected abstract BundleService extractBundleService(V view);
/**
* Returns the view managed by this presenter, or null if {@link #takeView} has never been
* called, or after {@link #dropView}.
*/
protected final V getView() {
return view;
}
/**
* @return true if this presenter is currently managing a view, or false if {@link #takeView} has
* never been called, or after {@link #dropView}.
*/
protected final boolean hasView() {
return view != null;
}
/** Like {@link Bundler#onEnterScope}. */
protected void onEnterScope(MortarScope scope) {
}
/**
* Like {@link Bundler#onLoad}, but called only when {@link #getView()} is not
* null, and debounced. That is, this method will be called exactly once for a given view
* instance, at least until that view is {@link #dropView(Object) dropped}.
*
* See {@link #takeView} for details.
*/
protected void onLoad(Bundle savedInstanceState) {
}
/** Like {@link Bundler#onSave}. */
protected void onSave(Bundle outState) {
}
/**
* Like {@link Bundler#onExitScope}. One subtlety to note is that a presenter may be created
* by a higher level scope than the one it is registered with, in which case it may receive
* multiple calls to this method.
*/
protected void onExitScope() {
}
}