Moxy is MVP library for Android

Overview

Moxy

This Moxy repository is deprecated and no longer supported.

Please migrate to the actual version of the Moxy framework at Moxy communuty repo.

Description

Maven Central license

Moxy is a library that helps to use MVP pattern when you do the Android Application. Without problems of lifecycle and boilerplate code!

The main idea of using Moxy: schematic_using See what's happening here in the wiki.

Capabilities

Moxy has a few killer features in other ways:

  • Presenter stay alive when Activity recreated(it simplify work with multithreading)
  • Automatically restore all that user see when Activity recreated(including dynamic content is added)
  • Capability to changes of many Views from one Presenter

Sample

View interface

public interface HelloWorldView extends MvpView {
	void showMessage(int message);
}

Presenter

@InjectViewState
public class HelloWorldPresenter extends MvpPresenter<HelloWorldView> {
	public HelloWorldPresenter() {
		getViewState().showMessage(R.string.hello_world);
	}
}

View implementation

public class HelloWorldActivity extends MvpAppCompatActivity implements HelloWorldView {

	@InjectPresenter
	HelloWorldPresenter mHelloWorldPresenter;

	private TextView mHelloWorldTextView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_hello_world);

		mHelloWorldTextView = ((TextView) findViewById(R.id.activity_hello_world_text_view_message));
	}

	@Override
	public void showMessage(int message) {
		mHelloWorldTextView.setText(message);
	}
}

Here you can see "Github" sample application.

Wiki

For all information check Moxy Wiki

Android studio templates

In order to avoid boilerplate code creating for binding activity, fragments and its presentation part, we propose to use Android Studio templates for Moxy.

Templates located in /moxy-templates

Links

Telegram channel (en)
Telegram channel (ru)
References
FAQ

Integration

Base modules integration:

dependencies {
  ...
  compile 'com.arello-mobile:moxy:1.5.5'
  annotationProcessor 'com.arello-mobile:moxy-compiler:1.5.5'
}

For additional base view classes MvpActivity and MvpFragment add this:

dependencies {
  ...
  compile 'com.arello-mobile:moxy-android:1.5.5'
}

If you are planning to use AppCompat, then you can use MvpAppCompatActivity and MvpAppCompatFragment. Then add this:

dependencies {
  ...
  compile 'com.arello-mobile:moxy-app-compat:1.5.5'
  compile 'com.android.support:appcompat-v7:$support_version'
}

AndroidX module integration

If you use AndroidX, use MvpAppCompatActivity and MvpAppCompatFragment add this (thanks to @jordan1997):

implementation 'tech.schoolhelper:moxy-x-androidx:1.7.0'

AndroidX(Google material) module integration

If you use google material, use MvpBottomSheetDialogFragment add this (thanks to @jordan1997):

implementation 'tech.schoolhelper:moxy-x-material:1.7.0'

Note: @jordan1997 creates fork of Moxy — feel free to use it fully (instead of use only this module dependency) on your opinion.

Kotlin

If you are using kotlin, use kapt instead of provided/apt dependency type:

apply plugin: 'kotlin-kapt'

dependencies {
  ...
  kapt 'com.arello-mobile:moxy-compiler:1.5.5'
}

ProGuard

Moxy is completely without reflection! No special ProGuard rules required.

License

The MIT License (MIT)

Copyright (c) 2016 Arello Mobile

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Comments
  • Duplicate entry MoxyReflector

    Duplicate entry MoxyReflector

    Добрый день. Столкнулся с проблемой в случае использования библиотеки Moxy одновременно в модуле приложения и модуле библиотеки. Поскольку 2 класса MoxyReflector имеют одинаковый пакет. Подскажите решение.

    Java.util.zip.ZipException: duplicate entry: com/arellomobile/mvp/MoxyReflector.class

    opened by user56i 30
  • Animate and Screen rotation 2

    Animate and Screen rotation 2

    Здравствуйте!

    Продолжение вот этого вопроса: #37 Есть одно активити и 3 дополнительных слоя, которые вызываем так:

    Activity:

    public class StartActivity extends MvpAppCompatActivity implements StartActivityView {
        @InjectPresenter
        StartActivityPresenter pStartActivityPresenter;
    
        @BindView(R.id.rootContainer) ViewGroup rootContainer;
    
        Scene scene_setusergendername;
        Scene scene_selectchild;
        Scene scene_setchildname;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_start);
    
            ButterKnife.bind(this);
    
            scene_setusergendername = Scene.getSceneForLayout(rootContainer, R.layout.scene_setusergendername, this);
            scene_selectchild = Scene.getSceneForLayout(rootContainer, R.layout.scene_selectchild, this);
            scene_setchildname = Scene.getSceneForLayout(rootContainer, R.layout.scene_setchildname, this);
        }
    
        public void goSetUserGenderName(View view) {
            pStartActivityPresenter.changeScene("SetUserGenderName");
        }
    
        public void goSelectChild(View view) {
            pStartActivityPresenter.changeScene("SelectChild");
        }
    
        public void goSetChildName(View view) {
            pStartActivityPresenter.changeScene("SetChildName");
        }
    
        @Override
        public void showScene_SetUserGenderName() {
            TransitionManager.go(scene_setusergendername, TransitionInflater.from(StartActivity.this).inflateTransition(R.transition.fade_out_in));
        }
    
        @Override
        public void showScene_SelectChild() {
            TransitionManager.go(scene_selectchild, TransitionInflater.from(StartActivity.this).inflateTransition(R.transition.fade_out_in));
        }
    
        @Override
        public void showScene_SetChildName() {
            TransitionManager.go(scene_setchildname, TransitionInflater.from(StartActivity.this).inflateTransition(R.transition.fade_out_in));
        }
    }
    

    Presenter:

    @InjectViewState
    public class StartActivityPresenter extends MvpPresenter<StartActivityView> {
        public StartActivityPresenter() {    }
    
        public void changeScene(String scenename) {
            if ("SetUserGenderName".equals(scenename)) {
                getViewState().showScene_SetUserGenderName();
            }
            else if ("SelectChild".equals(scenename)) {
                getViewState().showScene_SelectChild();
            }
            else if ("SetChildName".equals(scenename)) {
                getViewState().showScene_SetChildName();
            }
        }
    }
    

    View:

    public interface StartActivityView extends MvpView {
        void showScene_SetUserGenderName();
        void showScene_SelectChild();
        void showScene_SetChildName();
    }
    

    При нажатии кнопок на слоях, переходы обрабатываются нормально, претензий нет. Как только произошел поворот устройства, то срабатывает событие goSetUserGenderName. Т.е. после старта приложения нажали кнопку 1 раз - перешли на второй экран, нажали на кнопку снова - перешли на третий, еще раз - на четвертый экран. Повернули устройство - автоматом перешли на второй. Как сохранить состояние экрана в этом случае? isInRestoreState(this) не спасает.

    Спасибо!

    help wanted 
    opened by crysan 26
  • Проблема с getSupportFragmentManager().popBackStack()

    Проблема с getSupportFragmentManager().popBackStack()

    Ребята привет. Я конечно думаю что это у меня от некой неопытности, но всё же. getSupportFragmentManager().beginTransaction().replace(R.id.main_container, fragment).addToBackStack(null).commit(); При сворачивании приложения(onPause(), onStop()), и возврата на него(onResume()), всё идеально. Но при переключении на другой фрагмент(onPause(), onStop()), и возврата (onResume()) через getSupportFragmentManager().popBackStack(); дублируется состояние вьюхи (ViewState автоматически применяет к ней все команды, которые Presenter выдавал раньше), ну например адаптер теперь имеет не 2 элемента, а 4 (повторяющиеся естессно), в таком духе вобщем.

    Подскажите что делаю не так. Спасибо

    help wanted 
    opened by KaNcHeR 25
  • Совсем простой пример.

    Совсем простой пример.

    Здравствуйте!

    ЕСЛИ НЕ СЛОЖНО, то можете привести совсем простой пример с использованием архитектуры Moxy? Как например, в одной активити две кнопки и слой RelativeLayout. При нажатии на кнопки, в слой загружается один из двух фрагментов. Интересует реализация задачи с позиции Моху и сохранении жизненного цикла.

    СПАСИБО!

    help wanted 
    opened by crysan 23
  • MoxyReflector генерируется корректно через раз

    MoxyReflector генерируется корректно через раз

    Записал короткое двухминутное видео для иллюстрации проблемы http://take.ms/ovLac

    В проекте используется java и kotlin (1.1.3-2)

    Кусок build.gradle:

    buildscript {
        ext.kotlin_version = '1.1.3-2'
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.3.3'
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
            classpath 'com.google.gms:google-services:3.1.0'
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
    

    Кусок app/build.gradle:

    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-kapt'
    
    // скипнуто
    
    compile 'com.arello-mobile:moxy:1.5.3'
    compile 'com.arello-mobile:moxy-android:1.5.3'
    compile 'com.arello-mobile:moxy-app-compat:1.5.3'    
    kapt 'com.arello-mobile:moxy-compiler:1.5.3'
    
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    
    opened by asfdfdfd 21
  • Always need to do Clean Project

    Always need to do Clean Project

    Здравствуйте. Решил попробовать Moxy взял ваш код с презентации и написал на kotlin. Но вот беда появилась ошибка

    kotlin.UninitializedPropertyAccessException: lateinit property counterPresenter has not been initialized

    делаю Clean Project и нормально, потом делаю изменения в коде и опять ошибка пока не сделаю Clean Project.

    @InjectViewState
    class CounterPresenter : MvpPresenter<CounterView>() {
    
        var count: Int = 0
    
        init {
            viewState.showView(count)
        }
    
        fun onPlusClick() {
            count++
            viewState.showView(count)
        }
    }
    
    
    interface CounterView : MvpView {
        fun showView(count: Int)
    }
    
    class CounterFragment : MvpAppCompatFragment(), CounterView {
    
        @InjectPresenter
        lateinit var counterPresenter: CounterPresenter
    
        override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            return inflater?.inflate(R.layout.fragment, container, false)
        }
    
        override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            parentView.setBackgroundColor(arguments.getInt("color", 0))
    
            button.setOnClickListener {
                countPlus()
            }
        }
    
        fun countPlus() {
            counterPresenter.onPlusClick()
        }
        
        override fun showView(count: Int) {
            textCounter.text = "$count"
        }
    }
    
    
        compile 'com.arello-mobile:moxy:1.5.3'
        compile 'com.arello-mobile:moxy-android:1.5.3'
        compile 'com.arello-mobile:moxy-app-compat:1.5.3'
        kapt 'com.arello-mobile:moxy-compiler:1.5.3'
    
    opened by sanyok7734 19
  • Сохранение состояния фрагментов

    Сохранение состояния фрагментов

    Здравствуйте! Есть небольшая проблема с сохранением состояния фрагментов.

    1. Есть SplashScreenActivity, которая может показывать 1 из 2-х фрагментов. View:
    public interface SplashScreenView extends MvpView {
        void showMainActivityWithLoginFragment();  //если токен отсутствует
        void showMainActivityWithMainFragment(); //если есть токен
        void showErrorConnection();
        void goneErrorConnection();
    }
    
    1. MainActivity View:
    public interface MainActivityView extends MvpView {
        void showMainFragment();
        void showLoginFragment();
    }
    
    
    1. LoginFragment View:
    public interface LoginView extends MvpView {
    
        void visibleHeader();
        void goneHeader();
        void showSystemError(String errorText);
        void showPhoneError();
        void showPasswordError();
        void goneSystemError();
        void gonePhoneError();
        void gonePasswordError();
        void startErrorAnimation(TextView tvError);
        void showProgress(boolean progress);
        void showMainFragment();
    }
    
    1. MainFragment c viewPager В нём происходит только инициализация viewPager+tabLayout, view-интерфейс пустой.

    Насколько мне известно, по умолчанию, стоит стратегия AddToEndStrategy ко всем view-командам. Получается, что при перевороте экрана, накопленные команды во view запустятся заново. Но, при перевороте экрана, если я нахожусь в LoginFragment, состояние EditText не сохраняется. Так же, если я нахожусь в MainFragment, при перевороте открывается LoginFragment. Для решения этой проблемы пробовал использовать @StateStrategyType(SingleStateStrategy.class) к методам запуска MainFragment, но, ничего не изменилось)

    Скорее всего, проблема в неправильных стратегиях. Какие использовать в данном случае — не совсем понятно.

    opened by NoNews 18
  • Crash at startup

    Crash at startup

    gradle file

    apply plugin: 'com.neenbedankt.android-apt'
    ...
    compile 'com.android.support:appcompat-v7:25.0.1'
    ...
    apt 'com.google.dagger:dagger-compiler:2.8'
    compile 'com.google.dagger:dagger:2.8'
    ...
    compile 'com.arello-mobile:moxy:1.4.5'
    provided 'com.arello-mobile:moxy-compiler:1.4.5'
    compile 'com.arello-mobile:moxy-android:1.4.5'
    compile 'com.arello-mobile:moxy-app-compat:1.4.5'
    

    crash

    java.lang.NoClassDefFoundError: Failed resolution of: Lcom/arellomobile/mvp/MoxyReflector;
    at com.arellomobile.mvp.MvpProcessor.getMvpPresenters(MvpProcessor.java:82)
    at com.arellomobile.mvp.MvpDelegate.onCreate(MvpDelegate.java:101)
    at com.arellomobile.mvp.MvpAppCompatFragment.onCreate(MvpAppCompatFragment.java:23)
    at some.package.BaseFragment.onCreate(BaseFragment.java:26)
    
    help wanted 
    opened by morder 15
  • lateinit property Presenter has not been initialized

    lateinit property Presenter has not been initialized

    routesPresenter.getRoutes("18089") thrown exception:

    kotlin.UninitializedPropertyAccessException: lateinit property routesPresenter has not been initialized

    class MainFragment: MvpAppCompatFragment(), RoutesView {
        @InjectPresenter
        lateinit var routesPresenter: RoutesPresenter
    
        var adapter: RoutesAdapter = RoutesAdapter()
    
        companion object{
    
            fun newInstance(): MainFragment {
                return MainFragment()
            }
    
        }
    
        override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            App.appComponent.inject(this)
            val v = inflater?.inflate(R.layout.fragment_main, container, false)
            return v
        }
    
        override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
            recyclerView.layoutManager = LinearLayoutManager(activity)
            recyclerView.adapter = adapter
    
            routesPresenter.getRoutes("18089")
    
        }
    
        override fun onSuccess(list: List<Route>) {
             Log.d("MainFragment", "onSuccess")
            adapter.setItems(list)
        }
    
        override fun onEmptyData() {
            Log.d("MainFragment", "onEmpty")
        }
    
        override fun onError(e: Throwable) {
            Log.e("MainFragment", "error ${e.message}" )
        }
    }`
    help wanted 
    opened by jamesvanhallen 14
  • Callback method called multiply times

    Callback method called multiply times

    public void loadTeasers(int skip, boolean refresh, Category category) {
            getViewState().showProgress();
    
            Subscription s2 = ActiveAndroidHelper.getSources()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(teasers -> {
                        getViewState().onTeasersLoaded(teasers);
                        getViewState().hideProgress();
                    }, this::onError);
            unsubscribeOnDestroy(s2);
        }
    

    Suppose we have simple method which loads some data from network. I want to refresh my network data every onResume method. And, in this case, on each call of loadTeasers(true, new Category()), the callback method onTeasersLoaded(teasers) is called N times, where N is the number of onResume methods (and loadTeasers) executed. I think I need to unsubscribe and null the previous subsribition, but which method to use here? Thanks

    help wanted 
    opened by lectricas 13
  • FATAL EXCEPTION: ConcurrentModificationException при сохранении состояния активити

    FATAL EXCEPTION: ConcurrentModificationException при сохранении состояния активити

    FATAL EXCEPTION: java.util.ConcurrentModificationException at java.util.ArrayList$Itr.next(ArrayList.java:860) at java.util.AbstractCollection.addAll(AbstractCollection.java:343) at com.arellomobile.mvp.viewstate.MvpViewState.detachView(MvpViewState.java:84) at com.arellomobile.mvp.MvpPresenter.detachView(MvpPresenter.java:72) at com.arellomobile.mvp.MvpDelegate.onDetach(MvpDelegate.java:143) at com.arellomobile.mvp.MvpAppCompatActivity.onSaveInstanceState(MvpAppCompatActivity.java:44) at android.app.Activity.performSaveInstanceState(Activity.java:1555) at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1392) ...

    Вылетает при переключении на другое приложение (нажатии на home button). Вылетает не всегда, иногда на первый, иногда на третий-четвертый раз переключения. Иногда та же ошибка вызывает при восстановлении состояния, то есть в attachView().

    Кусок кода, в котором происходит данная ошибка: MVPViewState.java :

        public void detachView(View view) {
    	      mViews.remove(view);
    	      mInRestoreState.remove(view);
    		Set<ViewCommand<View>> currentState = Collections.newSetFromMap(new WeakHashMap<ViewCommand<View>, Boolean>());
    		currentState.addAll(mViewCommands.getCurrentState());
    		mViewStates.put(view, currentState);
    	   }
    

    Не совсем понятно, даже чисто теоретически при каких условиях может вылететь эта ошибка? Дебаггер в режиме логгирования отлавливает заход только одного потока в этот метод, после чего вылетает COncurrentModificationException.

    opened by epereskokov 12
  • Проблема с жизненным циклом MvpDelegate

    Проблема с жизненным циклом MvpDelegate

    Добрый день. На большом количестве устройств - от 9 до 12 версии андроид происходит вылет со следующей ошибкой

    Fatal Exception: java.util.ConcurrentModificationException at java.util.ArrayList$Itr.next(ArrayList.java:860) at moxy.MvpDelegate.onAttach(MvpDelegate.java:166) at moxy.MvpAppCompatFragment.onStart(MvpAppCompatFragment.java:38) at androidx.fragment.app.Fragment.performStart(Fragment.java:2731) at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:365) at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1206) at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1368) at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1446) at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1509) at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2637) at androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:2595) at androidx.fragment.app.Fragment.performStart(Fragment.java:2740) at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:365) at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1206) at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1368) at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1446) at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1509) at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2637) at androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:2595) at androidx.fragment.app.FragmentController.dispatchStart(FragmentController.java:258) at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:550) at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:210) at moxy.MvpAppCompatActivity.onStart(MvpAppCompatActivity.java:32) at modulbank.ru.commonapp.ui.main.MainActivity.onStart(MainActivity.kt:274) at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1456) at android.app.Activity.performStart(Activity.java:8076) at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3665) at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221) at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2215) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:346) at android.os.Looper.loop(Looper.java:475) at android.app.ActivityThread.main(ActivityThread.java:7889) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1009)

       Экран приложения, где происходит вылет не определен, крашлитика firebase выдает ошибку в вышеприведенном виде. Я так понимаю происходит рассинхронизация методов, в ходе чего происходит одновременная запись и чтение из листа, в связи с чем случается падение. 
    
    opened by ermac95 4
  • Tab adapter : FragmentStateAdapter (ViewPager2) doesn't work with MvpFragment

    Tab adapter : FragmentStateAdapter (ViewPager2) doesn't work with MvpFragment

    I'm trying to create TabAdapter class that inherits FragmentStateAdapter. So in function createFragment I need to return my framents which inherits MvpFragment, but it says: image And if function will inherits Fragment IDE says "Type mismatch" under my custom fragments: image Maybe I could use other class (not FragmentStateAdapter) which compatible with Moxy. I dont know how to fix it, pls help!

    opened by GramLun 0
  • Fix ClassCastException with local presenters

    Fix ClassCastException with local presenters

    After obfuscation, the names of the presenter classes have the same name, as a result of which an error occurs when we get the presenter from the map and bring it to a certain type.

    opened by KhanTF 0
  • Проблема в сгенерированном коде TestListView$$State

    Проблема в сгенерированном коде TestListView$$State

    Решил обновить проект. Перешел на Androidx и с com.github.moxy на com.arello-mobile Проблему со всеми импортами решил, но появилась ошибка кодогенерации moxy (то есть при com.github.moxy - такого не было)

    Мой gradle

    dependencies {
       ...
        // Moxy
        implementation "com.arello-mobile:moxy:$moxyVersion" //moxyVersion = '1.5.5'
        implementation 'tech.schoolhelper:moxy-x-androidx:1.7.0'
        kapt "com.arello-mobile:moxy-compiler:$moxyVersion"
       ...
    }
    
    

    Fragment

    class TestListFragment: BaseListFragment<String, TestListView, TestListPresenter, StringPaginationAdapter>(), TestListView {
    
        @InjectPresenter
        lateinit var presenter: TestListPresenter
    
        @ProvidePresenter
        fun providePresenter(): TestListPresenter = TestListPresenter()
    
        override fun initPresenter() = presenter
    
        override fun initAdapter() = StringPaginationAdapter()
    }
    

    Родительский Fragment

    abstract class BaseListFragment<
            ITEM: Any,
            VIEW: BaseListView<ITEM>,
            PRESENTER: BaseListPresenter<ITEM, VIEW>,
            A: BasePaginationAdapter<ITEM>
        > : BaseFragment(), BaseListView<ITEM>, PaginationRecyclerView.OnLoadMore {
    
        val listPresenter: PRESENTER by lazy { initPresenter() }
    
        abstract fun initPresenter(): PRESENTER
    
        val adapter: A by lazy { initAdapter() }
    
        open val emptyListLayoutRes = R.layout.layout_base_empty_list
        private var emptyLayout: View? = null
        override val layoutRes = R.layout.layout_base_list
    
        abstract fun initAdapter(): A
    
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
            val layout = super.onCreateView(inflater, container, savedInstanceState)
            layout.findViewById<FrameLayout>(R.id.flListContent)?.run {
                instanceEmptyList(inflater, container?.findViewById(R.id.flListContent))?.let {
                    emptyLayout = it
                    [email protected](emptyLayout)
                    hideEmptyList()
                }
            }
            return layout
        }
    
        private fun instanceEmptyList(inflater: LayoutInflater, container: ViewGroup?): View? {
            return if (emptyListLayoutRes != -1) { inflater.inflate(emptyListLayoutRes, container, false) }
            else { null }
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            initRecyclerView(rvList)
            initRefresher()
            super.onViewCreated(view, savedInstanceState)
        }
    
        open fun initRecyclerView(recyclerView: PaginationRecyclerView) {
            recyclerView.adapter = adapter
            recyclerView.withPagination = [email protected]
            recyclerView.listener = this
        }
    
        override fun updateList(list: List<ITEM>) {
            rlRefresher?.isRefreshing = false
            adapter.update(list)
        }
    
        open fun getRefresherLayout(): SwipeRefreshLayout? = rlRefresh
    
        open fun getRecyclerView(): PaginationRecyclerView = prvList
    }
    

    View

    interface TestListView : BaseListView<String>
    

    Родительский View

    @StateStrategyType(AddToEndSingleStrategy::class)
    interface BaseListView <I>: BaseView {
        ...
        fun updateList(list: List<I>)
        ...
    }
    

    Сгенерированный код TestListView$$State (Ругается на "List<? extends I>", Не знает "I")

    public class TestListView$$State extends MvpViewState<TestListView> implements TestListView {
    
            ......
    
    	@Override
    	public void updateList(List<? extends I> list) {
    		UpdateListCommand updateListCommand = new UpdateListCommand(list);
    		mViewCommands.beforeApply(updateListCommand);
    
    		if (mViews == null || mViews.isEmpty()) {
    			return;
    		}
    
    		for (TestListView view : mViews) {
    			view.updateList(list);
    		}
    
    		mViewCommands.afterApply(updateListCommand);
    	}
    
    	public class UpdateListCommand extends ViewCommand<TestListView> {
    		public final List<? extends I> list;
    
    		UpdateListCommand(List<? extends I> list) {
    			super("updateList", AddToEndSingleStrategy.class);
    
    			this.list = list;
    		}
    
    		@Override
    		public void apply(TestListView mvpView) {
    			mvpView.updateList(list);
    		}
    	}
    
            ......
    
    }
    
    opened by dfazullin 0
  • change import android.support.v7 ... to import androidx.appcompat

    change import android.support.v7 ... to import androidx.appcompat

    After migrating to AndroidX I faced the problem of underling errors in activities which extend MvpAppCompatActivity. I think it is because of using import android.support.v7 … instead of import androidx.appcompat… in moxy-x-app-compat-1.7.0-sources.jar!\com\arellomobile\mvp\MvpAppCompatActivity.java

    opened by 5oftware 0
Releases(v1.5.3)
  • v1.5.3(Jun 14, 2017)

  • v1.5.2(Jun 14, 2017)

  • v1.5.1(Apr 14, 2017)

  • 1.5.0(Apr 13, 2017)

  • v1.4.6(Mar 10, 2017)

  • v1.4.5(Jan 16, 2017)

  • v1.4.4(Jan 10, 2017)

  • v1.4.3(Dec 29, 2016)

  • v1.3.3(Dec 7, 2016)

  • v1.3.2(Nov 29, 2016)

    • Fixed MvpFragment/MvpAppCompatFragment lifecycle callbacks
    • MvpView will be detached from Presenter:
      • inside onSaveInstanceState, if it will be called. You be able to not commit fragments transaction allowing state loss! Just use commit or commitNow ! If you don't use Cicerone.
      • inside onStop otherwise
      • after MvpView will be restarted, it will apply only new commands!
      • after MvpView will be recreated, it will apply all commands.
    • Added OneExecutionStateStrategy
    • Small changes (like javadocs)

    PS: Added MvpDelegate.onDestroyView() which should be called when view will be destroyed. Causes of this is that detached view can stay alive. Example of use this beyond of Fragment is there.

    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Nov 14, 2016)

  • v1.1.2(Nov 5, 2016)

  • v1.1.1(Nov 2, 2016)

  • v1.1.0(Oct 22, 2016)

  • v1.0.3(Oct 17, 2016)

  • v1.0.2(Oct 11, 2016)

  • v1.0.1(Oct 5, 2016)

  • v1.0.0(Sep 30, 2016)

    • Allowed to set custom PresentersStore. This object help you manage presenters instances. It can help to mock presenters for View tests.
    • Code style changed

    :star2: Bonus! :boom:

    • Added MvpAppCompatActivity and MvpAppCompatFragment via moxy-app-compat module.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.4(Jul 8, 2016)

  • v0.5.3(Jul 7, 2016)

    • Now you can use typed MvpView. Thats allow you write some like this:
    interface LoadRefreshView<Data> extends MvpView
    {
        void showData(Data data)
    }
    
    public abstaract class LoadRefreshActivity<Data> extends MvpActivity implements LoadRefreshView<Data>
    {
        public abstract CustomAdapter<Data> getAdapter();
    
        void showData(Data data)
        {
            getAdapter().setData(data)
        }
    }
    
    public class NewsActivity extends LoadRefreshActivity<News>
    {
    ...
    }
    
    public class MessagesActivity extends LoadRefreshActivity<Message>
    {
    ...
    }
    
    
    • Changed moment when presenter was destroyed. Caution! Change your base classes similar to MvpActivity and MvpFragment
    • Memory optimization(presenter factory doesn't handle reference to default presenter)
    Source code(tar.gz)
    Source code(zip)
  • v0.4.1(Feb 29, 2016)

    • Annotation @GenerateViewState was deprecated because @InjectViewState generates view state, if it needed
    • Fixed bug of code generation for inner classes
    • Default StateStrategy of subclass View overrides default StateStrategy of View superclass
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Feb 29, 2016)

    • MvpDelegate inject presenters in each superclass too
    • Single ParamsProdiver for different factories
    • Check presenter fields with @InjectPresenter that field is public or package local
    • Added global weak presenter type
    • Allowed to apply @InjectPresenter to typed presenter
    Source code(tar.gz)
    Source code(zip)
Nucleus is an Android library, which utilizes the Model-View-Presenter pattern to properly connect background tasks with visual parts of an application.

Nucleus Deprecation notice Nucleus is not under develpment anymore. It turns out that Redux architecture scales way better than MVP/MVI/MVVM/MVxxx and

Konstantin Mikheev 2k Nov 18, 2022
A Model-View-Presenter / Model-View-Intent library for modern Android apps

Mosby A Model-View-Presenter and Model-View-Intent library for Android apps. Dependency dependencies { compile 'com.hannesdorfmann.mosby3:mvi:3.1.1

Hannes Dorfmann 5.5k Jan 5, 2023
Extendable MVI framework for Kotlin Multiplatform with powerful debugging tools (logging and time travel), inspired by Badoo MVICore library

Should you have any questions or ideas please welcome to the Slack channel: #mvikotlin Inspiration This project is inspired by Badoo MVICore library.

Arkadii Ivanov 460 Dec 31, 2022
Movie app that receives popular movies and allows the user to search for the specific movie through the Rest API with help of retrofit library &MVVM architecture.

MovieClue Millions of movies, TV shows and people to discover. Explore now Movie app that recieves popular movies and allow the user to search for spe

Shubham Tomar 6 Mar 31, 2022
📝 A demo todo/notes app which demonstrates the use of MVVM architecture, Navigation Component Library, Room Database, LiveData, Coroutines

?? MyNotes A demo notes/todo app which demonstrates the use of MVVM architecture, Navigation Component Library, Room Database, LiveData, Coroutines et

Raghav Aggarwal 89 Dec 23, 2022
Android Clean Architecture💎 Base Project Android with Kotlin and MVVM applying clean architecture

Android Clean Architecture?? Base Project Android with Kotlin and MVVM applying clean architecture

Mina Mikhail 103 Dec 2, 2022
Pick any of your favorite github repository and create a mini android app showing its details on an android app.

Github Browser Pick any of your favorite github repository and create a mini android app showing its details on an android app. Screens navigation gra

Prasoon 6 Oct 16, 2022
MVVM for Android

AndroidBinding MVVM for Android What's New Pre Compiled version available on root directory android-binding.gen.zip for activity/application template

Andy Tsui 350 Dec 17, 2022
A data-binding Presentation Model(MVVM) framework for the Android platform.

PLEASE NOTE, THIS PROJECT IS NO LONGER BEING MAINTAINED. As personal time contraints, I am currently unable to keep up. Please use official android da

RoboBinding open source 1.3k Dec 9, 2022
A full-featured framework that allows building android applications following the principles of Clean Architecture.

EasyMVP A powerful, and very simple MVP library with annotation processing and bytecode weaving. EasyMVP eliminates the boilerplate code for dealing w

null 1.3k Nov 19, 2022
MVVM RECIPE ANDROID APP Is an app where I show how to use MVVM, retrofit, dagger hilt, coroutine, liveData, Kotlin, navigation component, and so on...

MVVM RECIPE ANDROID APP Is an app where I show how to use MVVM, retrofit, dagger hilt, coroutine, liveData, kotlin, navigation component, and so on...

Isaias Cuvula 23 Dec 5, 2022
Membuat Aplikasi Github User MVVM dengan Android Studio

Membuat Aplikasi Github User MVVM dengan Android Studio. Ini hanya untuk referensi bagi kalian yang mengikuti Submission Dicoding Github User App.

Azhar Rivaldi 8 Nov 4, 2022
Kotlin Multiplatform Router for Android and iOS

A powerful Kotlin Multiplatform Router for Android and iOS Support I am happy to help you with any problem on gitter Feel free to open any new issue!

Sebastian Sellmair 343 Nov 16, 2022
Model-View-ViewModel architecture components for mobile (android & ios) Kotlin Multiplatform development

Mobile Kotlin Model-View-ViewModel architecture components This is a Kotlin Multiplatform library that provides architecture components of Model-View-

IceRock Development 638 Jan 2, 2023
Tutorial MVVM Fast Android Networking

MVVM-FAN Tutorial MVVM Fast Android Networking Tutorial Build with Android Studio https://youtu.be/nXX-NQIoGjk Tutorial Build with Step by Step https:

Azhar Rivaldi 7 Dec 6, 2022
🧬 Android DataBinding kit for notifying data changes from Model layers to UI layers on MVVM architecture.

?? Android DataBinding kit for notifying data changes from Model layers to UI layers on MVVM architecture.

Jaewoong Eum 275 Dec 21, 2022
LukohSplash is based on Android latest architectural components,Jetpack, and follows MVVM design pattern.

?? The LukohSplash by open-source contributor, Lukoh. LukohSplash LukohSplash is based on Android latest architectural components,Jetpack, and follows

Lukoh-Nam 86 Dec 20, 2022
Android Jetpack MVVM Boilerplate. Integrated with Jetpack dependencies, Hilt, Room, Okhttp, Retrofit, etc.

Android Jetpack MVVM Boilerplate Android Jetpack MVVM Boilerplate a Jetpack based, MVVM boilerplate template project for Modern Android. Features Here

Johnny Miller 12 Jul 7, 2022
An Android Template with MVVM and Clean Architecture

MVVMTemplate ??‍ A simple Android template that lets you create an Android project quickly. How to use ?? Just click on button to create a new repo st

Hossein Abbasi 561 Jan 8, 2023