支持 Mvp ConstraintLayout
Support MvpConstraintLayout
我自己尝试支持MvpConstraintLayout,直接从MvpLinearLayout复制代码
public abstract class MvpConstraintLayout<V extends MvpView, P extends MvpPresenter<V>>
extends ConstraintLayout implements MvpView, ViewGroupDelegateCallback<V, P> {
protected P presenter;
protected ViewGroupMvpDelegate<V, P> mvpDelegate;
public MvpConstraintLayout(Context context) {
super(context);
}
public MvpConstraintLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MvpConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* Get the mvp delegate. This is internally used for creating presenter, attaching and detaching
* view from presenter etc.
*
* <p><b>Please note that only one instance of mvp delegate should be used per android.view.View
* instance</b>.
* </p>
*
* <p>
* Only override this method if you really know what you are doing.
* </p>
*
* @return {@link ViewGroupMvpDelegate}
*/
@NonNull
protected ViewGroupMvpDelegate<V, P> getMvpDelegate() {
if (mvpDelegate == null) {
mvpDelegate = new ViewGroupMvpDelegateImpl<>(this, true);
}
return mvpDelegate;
}
@Override protected void onAttachedToWindow() {
super.onAttachedToWindow();
getMvpDelegate().onAttachedToWindow();
}
@Override protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getMvpDelegate().onDetachedFromWindow();
}
@SuppressLint("MissingSuperCall") @Override protected Parcelable onSaveInstanceState() {
return getMvpDelegate().onSaveInstanceState();
}
@SuppressLint("MissingSuperCall") @Override
protected void onRestoreInstanceState(Parcelable state) {
getMvpDelegate().onRestoreInstanceState(state);
}
/**
* Instantiate a presenter instance
*
* @return The {@link MvpPresenter} for this view
*/
public abstract P createPresenter();
@Override public P getPresenter() {
return presenter;
}
@Override public void setPresenter(P presenter) {
this.presenter = presenter;
}
@Override public V getMvpView() {
return (V) this;
}
@Override public final Parcelable superOnSaveInstanceState() {
return super.onSaveInstanceState();
}
@Override public final void superOnRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
}
}
然后,在代码中使用它
public class StatusBarLayout extends MvpConstraintLayout<StatusView, StatusPresenter>
implements StatusView {
public StatusBarLayout(Context context) {
super(context);
init();
}
public StatusBarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public StatusBarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
ButterKnife.bind(this, this);
}
@Override
public StatusPresenter createPresenter() {
return DaggerStatusBarLayoutComponent.builder().build().presenter();
}
private void init() {
View.inflate(getContext(), R.layout.layout_status, this);
}
}
在预览中,IDE 表示
java.lang.IllegalStateException: Could not find the surrounding Activity
at com.hannesdorfmann.mosby3.PresenterManager.getActivity(PresenterManager.java:231)
at com.hannesdorfmann.mosby3.mvp.delegate.ViewGroupMvpDelegateImpl.<init>(ViewGroupMvpDelegateImpl.java:70)
at com.skybornecn.ifdive.widgets.MvpConstraintLayout.getMvpDelegate(MvpConstraintLayout.java:55)
at com.skybornecn.ifdive.widgets.MvpConstraintLayout.onAttachedToWindow(MvpConstraintLayout.java:63)
at android.view.View.dispatchAttachedToWindow(View.java:15395)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2953)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2960)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2960)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2960)
at android.view.AttachInfo_Accessor.setAttachInfo(AttachInfo_Accessor.java:42)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:333)
at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:429)
at com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:368)
at com.android.tools.idea.rendering.RenderTask.compute(RenderTask.java:567)
at com.android.tools.idea.rendering.RenderTask.compute(RenderTask.java:549)
at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:863)
at com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:549)
at com.android.tools.idea.rendering.RenderTask.lambda$inflate(RenderTask.java:680)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
mosby PresenterManager我看过了,但还是不知道为什么。另外,安装到phone,布局显示就ok了。
更新:
这在 Mosby 3.0.1 中已修复。
这只是 Mosby 的 android 工具问题。
android 布局编辑器实际上实例化了 MvpConstraintLayout
的实例,以便在 Android Studio 中预览它。但是,Android Studio 不会通过将 MvpContraintLayout
之类的视图附加到真实的 Activity 来做到这一点,而是在内部使用一些模拟的 "context" 类似的东西。 Mosby 的 PresenterManager 在内部尝试为您的 MvpConstraintLayout
找到一个 Activity,但是在 Android Studio 中没有使用真正的 Activity(如前所述),因此 UI 编辑器显示此错误消息,当安装在 phone 上时它工作正常(因为使用了真正的 Activity)。
要解决这个问题,您必须在像这样调用委托之前使用 view.isInEditMode()
:
public abstract class MvpConstraintLayout<V extends MvpView, P extends MvpPresenter<V>>
extends ConstraintLayout implements MvpView, ViewGroupDelegateCallback<V, P> {
...
@Override protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!isInEditMode()) getMvpDelegate().onAttachedToWindow();
}
@Override protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (!isInEditMode()) getMvpDelegate().onDetachedFromWindow();
}
@SuppressLint("MissingSuperCall") @Override protected Parcelable onSaveInstanceState() {
if (!isInEditMode()) return getMvpDelegate().onSaveInstanceState();
return super.onSaveInstanceState();
}
@SuppressLint("MissingSuperCall") @Override
protected void onRestoreInstanceState(Parcelable state) {
if (!isInEditMode()) getMvpDelegate().onRestoreInstanceState(state);
}
/**
* Instantiate a presenter instance
*
* @return The {@link MvpPresenter} for this view
*/
public abstract P createPresenter();
@Override public P getPresenter() {
return presenter;
}
@Override public void setPresenter(P presenter) {
this.presenter = presenter;
}
@Override public V getMvpView() {
return (V) this;
}
@Override public final Parcelable superOnSaveInstanceState() {
return super.onSaveInstanceState();
}
@Override public final void superOnRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
}
}
这实际上是 ViewGroupMvpDelegate
应该在内部处理的事情。这应该用 Mosby 3.0.1 修复。
我自己尝试支持MvpConstraintLayout,直接从MvpLinearLayout复制代码
public abstract class MvpConstraintLayout<V extends MvpView, P extends MvpPresenter<V>>
extends ConstraintLayout implements MvpView, ViewGroupDelegateCallback<V, P> {
protected P presenter;
protected ViewGroupMvpDelegate<V, P> mvpDelegate;
public MvpConstraintLayout(Context context) {
super(context);
}
public MvpConstraintLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MvpConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* Get the mvp delegate. This is internally used for creating presenter, attaching and detaching
* view from presenter etc.
*
* <p><b>Please note that only one instance of mvp delegate should be used per android.view.View
* instance</b>.
* </p>
*
* <p>
* Only override this method if you really know what you are doing.
* </p>
*
* @return {@link ViewGroupMvpDelegate}
*/
@NonNull
protected ViewGroupMvpDelegate<V, P> getMvpDelegate() {
if (mvpDelegate == null) {
mvpDelegate = new ViewGroupMvpDelegateImpl<>(this, true);
}
return mvpDelegate;
}
@Override protected void onAttachedToWindow() {
super.onAttachedToWindow();
getMvpDelegate().onAttachedToWindow();
}
@Override protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getMvpDelegate().onDetachedFromWindow();
}
@SuppressLint("MissingSuperCall") @Override protected Parcelable onSaveInstanceState() {
return getMvpDelegate().onSaveInstanceState();
}
@SuppressLint("MissingSuperCall") @Override
protected void onRestoreInstanceState(Parcelable state) {
getMvpDelegate().onRestoreInstanceState(state);
}
/**
* Instantiate a presenter instance
*
* @return The {@link MvpPresenter} for this view
*/
public abstract P createPresenter();
@Override public P getPresenter() {
return presenter;
}
@Override public void setPresenter(P presenter) {
this.presenter = presenter;
}
@Override public V getMvpView() {
return (V) this;
}
@Override public final Parcelable superOnSaveInstanceState() {
return super.onSaveInstanceState();
}
@Override public final void superOnRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
}
}
然后,在代码中使用它
public class StatusBarLayout extends MvpConstraintLayout<StatusView, StatusPresenter>
implements StatusView {
public StatusBarLayout(Context context) {
super(context);
init();
}
public StatusBarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public StatusBarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
ButterKnife.bind(this, this);
}
@Override
public StatusPresenter createPresenter() {
return DaggerStatusBarLayoutComponent.builder().build().presenter();
}
private void init() {
View.inflate(getContext(), R.layout.layout_status, this);
}
}
在预览中,IDE 表示
java.lang.IllegalStateException: Could not find the surrounding Activity
at com.hannesdorfmann.mosby3.PresenterManager.getActivity(PresenterManager.java:231)
at com.hannesdorfmann.mosby3.mvp.delegate.ViewGroupMvpDelegateImpl.<init>(ViewGroupMvpDelegateImpl.java:70)
at com.skybornecn.ifdive.widgets.MvpConstraintLayout.getMvpDelegate(MvpConstraintLayout.java:55)
at com.skybornecn.ifdive.widgets.MvpConstraintLayout.onAttachedToWindow(MvpConstraintLayout.java:63)
at android.view.View.dispatchAttachedToWindow(View.java:15395)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2953)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2960)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2960)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2960)
at android.view.AttachInfo_Accessor.setAttachInfo(AttachInfo_Accessor.java:42)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:333)
at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:429)
at com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:368)
at com.android.tools.idea.rendering.RenderTask.compute(RenderTask.java:567)
at com.android.tools.idea.rendering.RenderTask.compute(RenderTask.java:549)
at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:863)
at com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:549)
at com.android.tools.idea.rendering.RenderTask.lambda$inflate(RenderTask.java:680)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
mosby PresenterManager我看过了,但还是不知道为什么。另外,安装到phone,布局显示就ok了。
更新: 这在 Mosby 3.0.1 中已修复。
这只是 Mosby 的 android 工具问题。
android 布局编辑器实际上实例化了 MvpConstraintLayout
的实例,以便在 Android Studio 中预览它。但是,Android Studio 不会通过将 MvpContraintLayout
之类的视图附加到真实的 Activity 来做到这一点,而是在内部使用一些模拟的 "context" 类似的东西。 Mosby 的 PresenterManager 在内部尝试为您的 MvpConstraintLayout
找到一个 Activity,但是在 Android Studio 中没有使用真正的 Activity(如前所述),因此 UI 编辑器显示此错误消息,当安装在 phone 上时它工作正常(因为使用了真正的 Activity)。
要解决这个问题,您必须在像这样调用委托之前使用 view.isInEditMode()
:
public abstract class MvpConstraintLayout<V extends MvpView, P extends MvpPresenter<V>>
extends ConstraintLayout implements MvpView, ViewGroupDelegateCallback<V, P> {
...
@Override protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!isInEditMode()) getMvpDelegate().onAttachedToWindow();
}
@Override protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (!isInEditMode()) getMvpDelegate().onDetachedFromWindow();
}
@SuppressLint("MissingSuperCall") @Override protected Parcelable onSaveInstanceState() {
if (!isInEditMode()) return getMvpDelegate().onSaveInstanceState();
return super.onSaveInstanceState();
}
@SuppressLint("MissingSuperCall") @Override
protected void onRestoreInstanceState(Parcelable state) {
if (!isInEditMode()) getMvpDelegate().onRestoreInstanceState(state);
}
/**
* Instantiate a presenter instance
*
* @return The {@link MvpPresenter} for this view
*/
public abstract P createPresenter();
@Override public P getPresenter() {
return presenter;
}
@Override public void setPresenter(P presenter) {
this.presenter = presenter;
}
@Override public V getMvpView() {
return (V) this;
}
@Override public final Parcelable superOnSaveInstanceState() {
return super.onSaveInstanceState();
}
@Override public final void superOnRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
}
}
这实际上是 ViewGroupMvpDelegate
应该在内部处理的事情。这应该用 Mosby 3.0.1 修复。