Sample code illustrating principles described at http://engineering.remind.com/android-code-that-scales/
remind101 / android-arch-sample Goto Github PK
View Code? Open in Web Editor NEWSample app for MVP Architecture on Android
Sample app for MVP Architecture on Android
Sample code illustrating principles described at http://engineering.remind.com/android-code-that-scales/
Hi, I wish to ask is there some specific reason to not create the presenters in onCreateViewHolder()
but in MvpRecyclerListAdapter.addInternal()
? Imagine you have an adapter of 1000 items. That means you'll have 1000 presenter instances while only few are enough at once (only for the currently bound view holders).
To reproduce, add enough counters to exceed the screen size. Add a count to an item. Scroll it off screen and then back on screen. The app crashes.
05-16 09:08:20.005 22412-22412/com.remind101.archexample E/AndroidRuntime: FATAL EXCEPTION: main Process: com.remind101.archexample, PID: 22412 java.lang.NullPointerException: Attempt to invoke virtual method 'void com.remind101.archexample.presenters.BasePresenter.bindView(java.lang.Object)' on a null object reference at com.remind101.archexample.MvpViewHolder.bindPresenter(MvpViewHolder.java:17) at com.remind101.archexample.MvpRecyclerAdapter.onBindViewHolder(MvpRecyclerAdapter.java:46) at com.remind101.archexample.MvpRecyclerAdapter.onBindViewHolder(MvpRecyclerAdapter.java:11) at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5217) at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5250) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4487) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4363) at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1961) at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1370) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1333) at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1161) at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1018) at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1492) at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:2416) at android.view.View.dispatchTouchEvent(View.java:10018) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2833) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2504) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2869) at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1861) at android.app.Activity.dispatchTouchEvent(Activity.java:3061) at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:60) at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2830) at android.view.View.dispatchPointerEvent(View.java:10253) at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5509) at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5345) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4790) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4843) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4809) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4950) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4817) at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5007) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4790) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4843) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4809) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4817)
The PresenterManager
class currently accepts a Bundle
object passed via the savePresenter(BasePresenter<?, ?> presenter, Bundle outState)
and the restorePresenter(Bundle savedInstanceState)
to keep a reference of a presenter. This makes a dependency on the Android framework.
What about passing a unique key string from the Activity
(or Fragment
) that uses this presenter? This will remove the dependency on the Bundle
class as well.
For example,
savePresenter(BasePresenter<?, ?> presenter, String key)
restorePresenter(String key)
and in Activity
's onCreate()
method,
private static final String MY_ACTIVITY_KEY = "login_activity";
.....
if (savedInstanceState == null) {
presenter = new MainPresenter();
} else {
presenter = PresenterManager.getInstance().restorePresenter(MY_ACTIVITY_KEY);
}
Hi,
In this code (from https://github.com/remind101/android-arch-sample/blob/master/app/src/main/java/com/remind101/archexample/MainActivity.java), the saved instance state may be not null (back navigation), and PresenterManager.getInstance().restorePresenter()
may return null (the cache use an expirationValue).
In this case, after this code, the presenter is null
and the app will certainly crash.
if (savedInstanceState == null) {
presenter = new MainPresenter();
} else {
presenter = PresenterManager.getInstance().restorePresenter(savedInstanceState);
}
Should the code not be more something like this or am I missing something?
if (savedInstanceState != null) {
presenter = PresenterManager.getInstance().restorePresenter(savedInstanceState);
}
if (presenter == null) {
presenter = new MainPresenter();
}
First, thank you for your nice blog post. I have fork and tried the app but not sure what is the intended functions of the app; therefore, I need to ask if it is intended to work this way. Following is the problem I encountered:
I created new counter using the count create button. After that I pressed the button increase to increase the value to 3 (means I press it three times). Everything was normal. Then I pressed back button until it was escaped from the app to home screen.
Then, I immediately went in the app. After the app loading, 3 new counters (= number of times I pressed the increase button) were created automatically. I have checked, the behavior also the same with decrease button. Would you mind to explain this situation?
Thank you so much.
I mean, this architecture works! But it also imports 18k methods for a skeleton app. Can we use something else for the cache that's more lightweight?
If the plus is pressed before the loading dialog disappears when opening the app, it crashes.
Question:
Article says "if your View needs a reference to the Model, you are probably doing it wrong too." What if i need to show data of some model without list and adapter, i need to pass that model from Presenter to Activity and Activity will hold that Model. ??
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.