0

我尝试自己支持 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$2.compute(RenderTask.java:567)
    at com.android.tools.idea.rendering.RenderTask$2.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$1(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,但仍然不知道为什么。另外,安装到手机上,布局显示就好了。

4

1 回答 1

0

更新:这已在 Mosby 3.0.1 中修复。


这只是 Mosby 的一个 android 工具问题。android 布局编辑器实际上实例化了一个 InstanceMvpConstraintLayout以在 Android Studio 中预览它。然而,Android Studio 并没有通过将 View like 附加MvpContraintLayout到真正的 Activity 来做到这一点,而是在内部使用了一些模拟的“上下文”类似的东西。Mosby 的 PresenterManager 在内部尝试为您的 Activity 查找 Activity MvpConstraintLayout,但在 Android Studio 中没有使用真正的 Activity(如前所述),因此 UI 编辑器会显示此错误消息,并且当安装在手机上时它可以正常工作(因为有一个真正的使用的活动)。

要解决这个问题,您必须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 中修复。

https://github.com/sockeqwe/mosby/issues/229

于 2017-03-29T11:45:05.303 回答