Coder Social home page Coder Social logo

arello-mobile / moxy Goto Github PK

View Code? Open in Web Editor NEW
1.6K 68.0 207.0 1.08 MB

Moxy is MVP library for Android

Home Page: https://github.com/Arello-Mobile/Moxy/wiki

License: MIT License

Java 90.08% FreeMarker 5.30% Kotlin 4.62%
moxy android mvp mvp-architecture architecture

moxy's People

Contributors

a-zaiats avatar acousticksan avatar alexeykorshun avatar cherryperry avatar dmdevgo avatar dosssik avatar ekursakov avatar fl1pflops avatar lion4ik avatar mohaxspb avatar rsajob avatar savinmike avatar senneco avatar seven332 avatar terrakok avatar v-grishechko avatar vovastelmashchuk avatar xanderblinov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

moxy's Issues

Проблема с пересозданием презентеров

Возникает проблема с пересозданием презентера после пересоздания активити если фрагмент этого презентера был в бекстеке.

Например имеем 2 фрагмента A и B с презентерами. Сначала показываем A потом реплейсим на B. Далее сворачиваем приложение. Активити уничтожается (для воспроизведения ставлю в настройках флаг “Do not keep activities”). При открытии приложения откроется фрагмент B, где презентер фрагмента B не пересоздался, а при нажатии бек откроется фрагмент A и презентер A - пересоздастся.

Фиксится указанием type = PresenterType.GLOBAL, но в таком случае презентер будет 1 для всех фрагментов этого типа.

Error with providing custom tags

I encountered a problem when writing custom tags provider on Kotlin, and decided to check whether it works on Java, so I wrote a test Activity:

interface TestView extends MvpView {
}
public class TestActivity extends MvpAppCompatActivity implements TestView {

    @InjectPresenter(type = PresenterType.GLOBAL)
    TestPresenter presenter;

    @ProvidePresenter(type = PresenterType.GLOBAL)
    TestPresenter providePresenter() {
        return new TestPresenter();
    }

    @ProvidePresenterTag(presenterClass = TestPresenter.class, type = PresenterType.GLOBAL)
    String provideTag() {
        return "test";
    }

    class TestPresenter extends MvpPresenter<TestView> {
    }
}

But I still get the same error when building:

Error:22:34:35.548 [ERROR] [system.err] java.lang.NullPointerException
22:34:35.549 [ERROR] [system.err] 	at com.arellomobile.mvp.compiler.PresenterBinderClassGenerator.bindTagProvidersToFields(PresenterBinderClassGenerator.java:160)
22:34:35.549 [ERROR] [system.err] 	at com.arellomobile.mvp.compiler.PresenterBinderClassGenerator.generate(PresenterBinderClassGenerator.java:104)
22:34:35.549 [ERROR] [system.err] 	at com.arellomobile.mvp.compiler.PresenterBinderClassGenerator.generate(PresenterBinderClassGenerator.java:51)
22:34:35.549 [ERROR] [system.err] 	at com.arellomobile.mvp.compiler.MvpCompiler.generateCode(MvpCompiler.java:142)
22:34:35.549 [ERROR] [system.err] 	at com.arellomobile.mvp.compiler.MvpCompiler.processInjectors(MvpCompiler.java:130)
22:34:35.549 [ERROR] [system.err] 	at com.arellomobile.mvp.compiler.MvpCompiler.throwableProcess(MvpCompiler.java:100)
22:34:35.549 [ERROR] [system.err] 	at com.arellomobile.mvp.compiler.MvpCompiler.process(MvpCompiler.java:84)
22:34:35.549 [ERROR] [system.err] 	at org.jetbrains.kotlin.annotation.AbstractAnnotationProcessingExtension.doRound(AnnotationProcessingExtension.kt:312)
22:34:35.549 [ERROR] [system.err] 	at org.jetbrains.kotlin.annotation.AbstractAnnotationProcessingExtension.process(AnnotationProcessingExtension.kt:252)
22:34:35.549 [ERROR] [system.err] 	at org.jetbrains.kotlin.annotation.AbstractAnnotationProcessingExtension.doAnnotationProcessing(AnnotationProcessingExtension.kt:239)
22:34:35.549 [ERROR] [system.err] 	at org.jetbrains.kotlin.annotation.AbstractAnnotationProcessingExtension.analysisCompleted(AnnotationProcessingExtension.kt:131)
22:34:35.549 [ERROR] [system.err] 	at org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.java:160)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(TopDownAnalyzerFacadeForJVM.java:79)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.analyze(KotlinToJVMBytecodeCompiler.kt:362)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:126)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:355)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules(KotlinToJVMBytecodeCompiler.kt:130)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:183)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:52)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.java:199)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.gradle.tasks.KotlinCompile.compileNotIncremental(Tasks.kt:594)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.gradle.tasks.KotlinCompile.callCompiler(Tasks.kt:419)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.gradle.tasks.KotlinCompile.callCompiler(Tasks.kt:151)
22:34:35.550 [ERROR] [system.err] 	at org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile.execute(Tasks.kt:117)
22:34:35.550 [ERROR] [system.err] 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
22:34:35.550 [ERROR] [system.err] 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
22:34:35.551 [ERROR] [system.err] 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
22:34:35.551 [ERROR] [system.err] 	at java.lang.reflect.Method.invoke(Method.java:498)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:245)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:221)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:232)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:210)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:66)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
22:34:35.551 [ERROR] [system.err] 	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
22:34:35.552 [ERROR] [system.err] 	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:153)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.internal.Factories$1.create(Factories.java:22)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:53)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:150)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:98)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:92)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:63)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:92)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:83)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:99)
22:34:35.553 [ERROR] [system.err] 	at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:46)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:58)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:48)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:30)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:81)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:46)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
22:34:35.554 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.util.Swapper.swap(Swapper.java:38)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
22:34:35.555 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
22:34:35.556 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
22:34:35.556 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
22:34:35.556 [ERROR] [system.err] 	at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:237)
22:34:35.556 [ERROR] [system.err] 	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
22:34:35.556 [ERROR] [system.err] 	at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
22:34:35.556 [ERROR] [system.err] 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
22:34:35.556 [ERROR] [system.err] 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
22:34:35.556 [ERROR] [system.err] 	at java.lang.Thread.run(Thread.java:745)
22:34:35.556 [ERROR] [system.err] Moxy compilation failed; see the compiler error output for details (java.lang.NullPointerException)
22:34:35.637 [ERROR] [org.jetbrains.kotlin.gradle.tasks.KotlinCompile_Decorated] e: C:\Users\vandrikeev\Projects\test\app\src\main\java\ru\andrikeev\android\test\application\App.kt: (1, 1): Some error(s) occurred while processing annotations. Please see the error messages above.
22:34:35.637 [ERROR] [org.jetbrains.kotlin.gradle.tasks.KotlinCompile_Decorated] e: C:\Users\vandrikeev\Projects\test\app\src\main\java\ru\andrikeev\android\test\application\App.kt: (10, 52): Unresolved reference: DaggerAppComponent
22:34:35.637 [ERROR] [org.jetbrains.kotlin.gradle.tasks.KotlinCompile_Decorated] e: C:\Users\vandrikeev\Projects\test\app\src\main\java\ru\andrikeev\android\test\application\App.kt: (24, 24): Unresolved reference: DaggerAppComponent
22:34:35.641 [ERROR] [org.gradle.BuildExceptionReporter] 
22:34:35.641 [ERROR] [org.gradle.BuildExceptionReporter] FAILURE: Build failed with an exception.
22:34:35.641 [ERROR] [org.gradle.BuildExceptionReporter] 
22:34:35.641 [ERROR] [org.gradle.BuildExceptionReporter] * What went wrong:
22:34:35.641 [ERROR] [org.gradle.BuildExceptionReporter] Execution failed for task ':app:compileDebugKotlin'.
22:34:35.641 [ERROR] [org.gradle.BuildExceptionReporter] > Compilation error. See log for more details
22:34:35.641 [ERROR] [org.gradle.BuildExceptionReporter] 
22:34:35.641 [ERROR] [org.gradle.BuildExceptionReporter] * Try:
22:34:35.641 [ERROR] [org.gradle.BuildExceptionReporter] Run with --stacktrace option to get the stack trace. 


It seems to me that the problem with Kotlin annotations processing, but i'm not sure and have no idea how to fix it.

ViewPager MVP

Привет, мне очень понравилась ваша библиотека, просто потрясная реализация мвп) всё очень удобно и красиво) Единственное я бы хотел спросить как правильно поступить, что бы не городить велосипеды. У меня есть ViewPager с 3мя одинаковыми фрагментами, но они отображают разную информацию. При создании этих фрагментов, они все инжектятся к одному и тому же презентору) тот естественно запоминает состояние последнего добавленного фрагмента и после чего все 3 фрагмента начинают показывать одну и ту же информацию) Можно как то создавать для каждого фрагмента, свой отдельный презентер? или же есть какие то другие варианты?

Build fails if View method have return value

If you add a method that returns a value to the View (both interface and implementation) - generated code will contain error and won't be compiled.
Specifically, generated method with return value will contain:

    if (mViews == null || mViews.isEmpty())
    {
        return; //compile-time error. missing return value
    }

This statement should return null; at least.

How do you use dagger 2 injection with Moxy

Trying to use the @InjectPresenter in the Views and @InjectViewState preceding the presenter classes but my presenter classes also need to inject modules of their own which I'm doing via the constructor but I get this error

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.jackthreads.android/com.jackthreads.android.activities.PageActivity}: java.lang.IllegalStateException: Unable to instantiate class com.jackthreads.android.presenters.PagePresenter: make sure class name exists, is public, and has an empty constructor that is public
     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2661)
     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
     at android.app.ActivityThread.access$900(ActivityThread.java:172)
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421)
     at android.os.Handler.dispatchMessage(Handler.java:102)
     at android.os.Looper.loop(Looper.java:145)
     at android.app.ActivityThread.main(ActivityThread.java:5835)
     at java.lang.reflect.Method.invoke(Native Method)
     at java.lang.reflect.Method.invoke(Method.java:372)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
  Caused by: java.lang.IllegalStateException: Unable to instantiate class com.jackthreads.android.presenters.PagePresenter: make sure class name exists, is public, and has an empty constructor that is public
     at com.arellomobile.mvp.DefaultPresenterFactory.createPresenter(DefaultPresenterFactory.java:30)
     at com.arellomobile.mvp.DefaultPresenterFactory.createPresenter(DefaultPresenterFactory.java:11)
     at com.arellomobile.mvp.MvpProcessor.getMvpPresenter(MvpProcessor.java:125)
     at com.arellomobile.mvp.MvpProcessor.getMvpPresenters(MvpProcessor.java:177)
     at com.arellomobile.mvp.MvpDelegate.onCreate(MvpDelegate.java:110)
     at com.jackthreads.android.activities.MvpAppCompatActivity.onCreate(MvpAppCompatActivity.java:15)

Searching Moxy and Dagger 2 brings up nothing and it seems like they're messing each other up.

NullPointer when view method call MenuItem

Hi, Im had issues when view method has AddToEndSingle strategy and implementation of this method call MenuItems. Basically in the moment after screen rotate menu items still null when ViewState try to reapply commands to view. What can I do in that situation?

Некорректный app-compat fragment

В обычном фрагменте есть фикс на закрытие активности:

if (isRemoving() || getActivity().isFinishing()) {
    getMvpDelegate().onDestroy();
}

В саппортовском фрагменте этого фикса нет:

if (isRemoving()) {
    getMvpDelegate().onDestroy();
}

Шаблоны (Templates)

В шаблонах, еще старые подставляет классы вместо
MvpAppCompatActivity /MvpAppCompatFragment

Not an issue But

This looks very similar to the mosby library by hannes.. Could you please tell me what advantages i would've if i upgrade to moxy?

Best practice to save state of input fields

Hello. Is there a best practice for Moxy to save view state of input fields?
For example, a scheme below causes looping.

//LoginView
void onCreate(){
  editTextLogin.afterTextChanged((text) -> loginPresenter.onLoginChanged(text));
}
void showLogin(String login){
  editTextLogin.setText(login);
}


//LoginPresenter
void onLoginChanged(String newLogin){
  this.login = newLogin;
  getViewState().showLogin(newLogin);
}

@InjectPresenter(type=PresenterType.GLOBAL) requires tag value

Is it possible to not set the tag value (leave it "" as default) but have a single global Presenter? @InjectPresenter(type=PresenterType.GLOBAL) vs @InjectPresenter(type=PresenterType.GLOBAL,tag="tag") if I actually need single Presenter of such type around the application.

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}" )
    }
}`

Create moxy-app-compat module

Copypaste MvpActivity to MvpAppCompatActivity in each project is ugly. Should provide module, that depends on app compat and provide MvpAppCompatActivity.

@InjectPresenter не работает

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

Сделал всё как по вашему примеру. Написал LoginActivity, LoginPresenter, LoginView. Приложение запускается и крашится из-за того , что LoginPresenter, объявленный в активити, остается null.
Пожалуйста, подскажите в чем может быть проблема. Вот пример кода.

public class LoginActivity extends MvpActivity implements LoginView {

    @InjectPresenter
    LoginPresenter mLoginPresenter;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        Button mSignInButton = (Button) findViewById(R.id.sign_in_button);
        mSignInButton.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v) {
                attemptLogin();
            }
        });

        mErrorDialog = new AlertDialog.Builder(this)
                .setTitle(R.string.app_name)
                .setOnCancelListener(new OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialogInterface) {
                        mLoginPresenter.onErrorCancel();
                    }
                }).create();
        mLoginFormView = findViewById(R.id.login_form);
        mProgressView = findViewById(R.id.login_progress);
    }
private void attemptLogin() {
        mLoginPresenter.login(mUsernameView.getText().toString(), mPasswordView.getText().toString(),this);
}
@InjectViewState
public class LoginPresenter extends MvpPresenter<LoginView> {


    public void login(String username, String password, Context context) {
//какой-то код
 }
}

CHANGELOG.md

Можете вести ченджлог по версиям? А то что-то обновляется, а что именно непонятно.

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

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

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

СПАСИБО!

Hi

How to use this awesome library on recycleview adapter?

presenter при повороте экрана

Имеется активити с проигрыванием видео-потока с возможностью выбора архива видео. Проигрывание видео начинается в onCreate через вызов презентера, потом условно выбираю проигрывание архива, поворачиваю экран, продолжает играть онлайн, а не архив.
онлайн видео при создании:

в активити в onCreate вызывается метод getCamera, в котором получаем ссылку на stream-поток.

 protected void onCreate(final Bundle savedInstanceState) {
     videoPlayPresenter.getCamera(cameraId);
      }
public void getCamera(Long camId){
        String cookie = "JSESSIONID=".concat(AuthUtils.getSessionId()).concat("; XSRF- TOKEN=").concat(AuthUtils.getToken()).concat("; remember- me=").concat(AuthUtils.getRememberMe());
         final Observable<BackendData> observable = RxUtils.wrapRetrofitCall(service.getCamera(cookie,  AuthUtils.getToken(), camId, false));
         RxUtils.wrapAsync(observable)
                  .subscribe(
                          backendData -> {
                              ObjectMapper mapper = new ObjectMapper();
                              CameraSmallDTO cameraSmallDTO = mapper.convertValue(backendData.getData(),   CameraSmallDTO.class);
                             getViewState().getCamera(cameraSmallDTO);
                         },
                          throwable -> showError()
                   );
    }

Если все хорошо, вызывается метод в getCamera из активити и в нем вызывается метод play из презентера для проигрывания видео.

  @Override
     public void getCamera(CameraSmallDTO camera) {
         cameraSmallDTO = camera;
         rtmpLink = cameraSmallDTO.getInfo().getUrl();
         devCode = cameraSmallDTO.getKey();
         videoPlayPresenter.play(rtmpLink, false, null, null);
     }

Когда я хочу проиграть архив, я выбираю время и в активити вызываю метод play из презентера, в нем запрашивается новая ссылка на stream-поток, если это архив или продолжает играть онлайн.

 public void play(String path, boolean flagArchive, Long camId, Date date){
        if (camId != null && date != null){
            DateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm");
            String dateStart = df.format(date);
            Calendar calendar  = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.MINUTE, 10);
            String dateStop = df.format(calendar.getTime());
            String cookie = "JSESSIONID=".concat(AuthUtils.getSessionId()).concat("; XSRF-TOKEN=").concat(AuthUtils.getToken()).concat("; remember-me=").concat(AuthUtils.getRememberMe());
            Observable<BackendData> observable = RxUtils.wrapRetrofitCall(service.getStreamArchive(cookie, AuthUtils.getToken(), camId, dateStart, dateStop, true));
            RxUtils.wrapAsync(observable)
                    .subscribe(response ->
                                    getViewState().play(response.getData().toString(), true),
                            throwable -> getViewState().play(path, false)
                    );
        } else getViewState().play(path, flagArchive);
    }

Если я выбрал играть архив, и повернул экран - начинает ссылка на онлайн, а не архив онлайн

Got lateinit property mainPresenter has not been initialized in Kotlin

hey, I have this code:

class MainActivity : MvpAppCompatActivity(), MainViewInterface, AnkoLogger {

    @InjectPresenter
    lateinit var mainPresenter: MainPresenter

    val recyclerView: RecyclerView by bindView(R.id.track_list)
    val fab: FloatingActionButton by bindView(R.id.fab)
    val cLayout: CoordinatorLayout by bindView(R.id.main_coordinator)

    val realm: Realm = Realm.getDefaultInstance()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        MyApplication.graph.inject(this)
        recyclerView.layoutManager = LinearLayoutManager(this)
        mainPresenter.loadAllTracks() //error here
    }

ViewState:

@StateStrategyType(value = AddToEndSingleStrategy::class) //not sure about this thing
interface MainViewInterface : MvpView {
    fun successLoadingTracks(tracks: List<Track>)
}

Presenter

@InjectViewState
class MainPresenter : MvpPresenter<MainViewInterface>() {

    fun loadAllTracks() {
        viewState.successLoadingTracks(ArrayList())
    }
}

And I get this error when trying to access presenter var. Kotlin plugin is up to date.

jack and annotationProcessor

I try use jack, java8 and annotationProcessor. But I get error

java.lang.StringIndexOutOfBoundsException: String index out of range: -1
        at java.lang.String.substring(String.java:1931)
        at com.arellomobile.mvp.compiler.Util.getFullClassName(Util.java:105)
        at com.arellomobile.mvp.compiler.Util.getFullClassName(Util.java:97)
        at com.arellomobile.mvp.compiler.PresenterInjectorRules.checkEnvironment(PresenterInjectorRules.java:70)
        at com.arellomobile.mvp.compiler.PresenterInjectorRules.checkAnnotation(PresenterInjectorRules.java:44)
        at com.arellomobile.mvp.compiler.MvpCompiler.checkInjectors(MvpCompiler.java:115)
        at com.arellomobile.mvp.compiler.MvpCompiler.throwableProcess(MvpCompiler.java:96)
        at com.arellomobile.mvp.compiler.MvpCompiler.process(MvpCompiler.java:84)

To reproduce modify build.gradle of sample-github like this

apply plugin: 'com.android.application'

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    compileSdkVersion 25
    buildToolsVersion "25.0.0"

    defaultConfig {
        applicationId "com.arellomobile.mvp.sample.github"
        minSdkVersion 14
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        jackOptions {
            enabled true
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    lintOptions {
        abortOnError false
    }
}

def support = '25.0.0'
def retrofit = '2.1.0'
def dagger = '2.7'
def butterKnife = "8.4.0"

dependencies {
    testCompile "junit:junit:4.12"
    compile "com.android.support:appcompat-v7:$support"
    compile "com.android.support:design:$support"

    compile "com.j256.ormlite:ormlite-core:4.48"
    compile "com.j256.ormlite:ormlite-android:4.48"

    compile "com.google.code.gson:gson:2.5"

    compile "com.jakewharton:butterknife:$butterKnife"

    compile "com.squareup.retrofit2:retrofit:$retrofit"
    compile "com.squareup.retrofit2:converter-gson:$retrofit"
    compile "com.squareup.retrofit2:adapter-rxjava:$retrofit"
    compile "com.squareup.picasso:picasso:2.5.2"
    compile "com.squareup:otto:1.3.8"

    compile "io.reactivex:rxjava:1.1.0"
    compile "io.reactivex:rxandroid:1.1.0"

    compile "com.google.dagger:dagger:$dagger"
    provided "org.glassfish:javax.annotation:10.0-b28"

    annotationProcessor "com.jakewharton:butterknife-compiler:$butterKnife"
    annotationProcessor "com.google.dagger:dagger-compiler:$dagger"

    testCompile "junit:junit:4.12"
    testCompile "org.mockito:mockito-all:1.10.19"
    testCompile "org.hamcrest:hamcrest-all:1.3"
    testCompile "org.robolectric:robolectric:3.1-rc1"

    compile 'com.arello-mobile:moxy:1.2.0'
    annotationProcessor 'com.arello-mobile:moxy-compiler:1.2.0'
}

Dialog

Hi, I understand how to use moxy in activities and fragments, but how can I use moxy in android dialogs? Can you provide an example code, please?

java.lang.NoSuchMethodError when call MvpAppCompatFragment.onDestroy()

java.lang.NoSuchMethodError: No virtual method getActivity()Landroid/app/Activity; in class Lcom/arellomobile/mvp/MvpAppCompatFragment; or its super classes (declaration of 'com.arellomobile.mvp.MvpAppCompatFragment' appears in ...)
at com.arellomobile.mvp.MvpAppCompatFragment.onDestroy(MvpAppCompatFragment.java:40)
at android.support.v4.app.Fragment.performDestroy(Fragment.java:2322)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1240)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1272)
at android.support.v4.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:2186)
at android.support.v4.app.FragmentController.dispatchDestroy(FragmentController.java:271)
at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:388)
at android.support.v7.app.AppCompatActivity.onDestroy(AppCompatActivity.java:209)
at com.arellomobile.mvp.MvpAppCompatActivity.onDestroy(MvpAppCompatActivity.java:26)
at android.app.Activity.performDestroy(Activity.java:6169)
at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1141)
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3693)
at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3724)
at android.app.ActivityThread.access$1400(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1357)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

Generating ViewState for typed View

I have an error, when trying to build project.
The problem is with generated ViewState's

I have View:

interface LceView<in M : Any> : MvpView {

    fun showLoading(pullToRefresh: Boolean = false)

    fun showContent(model: M)

    fun showError(e: Throwable, pullToRefresh: Boolean = false)
}

But generated LceViewState generated with [ ] around Model template:

public class LceView$$State<M> extends MvpViewState<LceView> implements LceView<[M]> {
    private ViewCommands<LceView> mViewCommands = new ViewCommands<>();

    @Override
    public void restoreState(LceView view) {
        if (mViewCommands.isEmpty()) {
            return;
        }

        mViewCommands.reapply(view);
    }

    @Override
    public  void showLoading(boolean pullToRefresh) {
        ShowLoadingCommand showLoadingCommand = new ShowLoadingCommand(pullToRefresh);
        mViewCommands.beforeApply(showLoadingCommand);

        if (mViews == null || mViews.isEmpty()) {
            return;
        }

        for(LceView view : mViews) {
            view.showLoading(pullToRefresh);
        }

        mViewCommands.afterApply(showLoadingCommand);
    }

    @Override
    public  void showContent(M model) {
        ShowContentCommand showContentCommand = new ShowContentCommand(model);
        mViewCommands.beforeApply(showContentCommand);

        if (mViews == null || mViews.isEmpty()) {
            return;
        }

        for(LceView view : mViews) {
            view.showContent(model);
        }

        mViewCommands.afterApply(showContentCommand);
    }

    @Override
    public  void showError(java.lang.Throwable e, boolean pullToRefresh) {
        ShowErrorCommand showErrorCommand = new ShowErrorCommand(e, pullToRefresh);
        mViewCommands.beforeApply(showErrorCommand);

        if (mViews == null || mViews.isEmpty()) {
            return;
        }

        for(LceView view : mViews) {
            view.showError(e, pullToRefresh);
        }

        mViewCommands.afterApply(showErrorCommand);
    }


    private class ShowLoadingCommand extends ViewCommand<LceView> {
        public final boolean pullToRefresh;

        ShowLoadingCommand(boolean pullToRefresh) {
            super("showLoading", com.arellomobile.mvp.viewstate.strategy.AddToEndStrategy.class);
            this.pullToRefresh = pullToRefresh;
        }

        @Override
        public void apply(LceView mvpView) {
            mvpView.showLoading(pullToRefresh);
        }
    }

    private class ShowContentCommand extends ViewCommand<LceView> {
        public final M model;

        ShowContentCommand(M model) {
            super("showContent", com.arellomobile.mvp.viewstate.strategy.AddToEndStrategy.class);
            this.model = model;
        }

        @Override
        public void apply(LceView mvpView) {
            mvpView.showContent(model);
        }
    }

    private class ShowErrorCommand extends ViewCommand<LceView> {
        public final java.lang.Throwable e;
        public final boolean pullToRefresh;

        ShowErrorCommand(java.lang.Throwable e, boolean pullToRefresh) {
            super("showError", com.arellomobile.mvp.viewstate.strategy.AddToEndStrategy.class);
            this.e = e;
            this.pullToRefresh = pullToRefresh;
        }

        @Override
        public void apply(LceView mvpView) {
            mvpView.showError(e, pullToRefresh);
        }
    }
}

p.s. I tried use invariant for M, it didn't help

Не сохраняется состояние

Обновился с версии 0.5.2 -> 0.5.4 ViewState перестало сохранять свое состояние.

Например: Есть метод который показывает диалоговое окно @StateStrategyType(AddToEndSingleStrategy.class)
void showLoadingDialog();

при перевороте экрана, диалог не показывается, а на 0.5.2. - показывается

[Vote] Presenters scope.

Hi,

We think about new feature. We want to make able to put presenter to some scope. Until scope will be closed these presenter instances will be injected. And allow delegate to close scope. And then presenters of scope will be destroyed.

We don't think about interface currently. Only about feature.

Welcome any suggestions.

StateStrategy for "clearable" ViewCommands

Let's examine this use-case: presenter adds group of markers to map, removes some of them afterwards, some - not. This process may repeate multitude of times, then orientation changes, and ViewState is reapplied to newly attached View. From user perspective it would be lengthy process of repeating all actions user had done, while he just needs markers which "survived" removal.

To solve this issue it would be great to add one more StateStrategy - TraceStrategy and ClearStrategy (counterpart)

For example, let's have a method:

public class MapView implements MvpView {
   /*
   * Some other code
   */
   private int counter = 0;

   @StateStrategy(value = TraceStrategy.class, tag = "addMarker")
   int addMarker(double lat, double lon) {
      // ...
      return counter++;
   }
}

In result of this ViewCommand on top of ViewCommand stack new ViewCommand should be added with tag = "addMarker0". Running this command again will result in ViewCommand with tag = "addMarker1" and so on. Number is value returned by method (more generally - toString() of returned Object).

Now counterpart for addMarker will be

public class MapView implements MvpView {
   /*
   * Some other code
   */
   private int counter = 1; // Affected by addMarker()

   @StateStrategy(value = ClearStrategy.class, tag = "addMarker")
   int removeMarker(int id) {
      // ...
      return --counter;
   }
}

This ViewCommand appends to tag returned value than searches ViewCommand with tag whose value is, for instance, "addMarker0", removes it and does not put itself in stack.

Drawbacks of this approach are:

  • Proguard should handle tag of ClearStrategy appropriately
  • remove* methods shoud return its argument

P.S.
If there is no return value required, for example, just one marker can be added, than TraceStrategy and ClearStrategy should also take care of this.

P.P.S
Issue instead of PR because I think there is discussion part in this issue.

NullPointerException в генерируемом коде после обновления до 1.3.2

View interface:

public interface CloseableView extends MvpView {
    @StateStrategyType(SkipStrategy.class)
    void close();
}

View implementation (Fragment):

@Override
public void close() {
    if (getActivity() != null) getActivity().onBackPressed();
}

Presenter:

public void apply() {
    localBroadcastManager.sendBroadcast(intent);
    getViewState().close();
}

По нажатию на кнопку во вью вызывается метод apply презентера. В close текущий фрагмент выкидывается из backstack'a, и на его место встает предыдущий. В итоге во CloseableView$$State в методе close выкидывается NullPointerException т.к. getCurrentState теперь возвращает null:

@Override
public  void close() {
    CloseCommand closeCommand = new CloseCommand();
    mViewCommands.beforeApply(closeCommand);

    if (mViews == null || mViews.isEmpty()) {
        return;
    }

    for(CloseableView view : mViews) {
        view.close();
        getCurrentState(view).add(closeCommand);
    }

    mViewCommands.afterApply(closeCommand);
}

Проблема с 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 (повторяющиеся естессно), в таком духе вобщем.

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

Moxy with Kotlin

Is Moxy normally work with Kotlin?
I have

@InjectViewState
class MainPresenter : MvpPresenter<MainView>() {

    private var mSubscriptions: CompositeSubscription? = null
    lateinit var mNetworkManager: NetworkManager
    lateinit var mDbManager: DatabaseManager
    lateinit var mRxFactory: RxSchedulersFactory

    init {
        mSubscriptions = CompositeSubscription()
        App.appComponent.inject(this)
    }
class MainActivity : MvpAppCompatActivity(), MainView{

    @InjectPresenter
    lateinit var mPresenter: MainPresenter
open class MvpAppCompatActivity : AppCompatActivity() {

    lateinit var mMvpDelegate: MvpDelegate<out MvpAppCompatActivity>

    init {
        mMvpDelegate = MvpDelegate<MvpAppCompatActivity>(this)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mMvpDelegate.onCreate()
    }

    override fun onStart() {
        super.onStart()
        mMvpDelegate.onStart()
    }

    override fun onSaveInstanceState(outState: Bundle?) {
        super.onSaveInstanceState(outState)
        mMvpDelegate.onSaveInstanceState(outState)
    }

    override fun onStop() {
        super.onStop()
        mMvpDelegate.onStop()
    }

    override fun onDestroy() {
        super.onDestroy()
        mMvpDelegate.onDestroy()
    }
}
    compile 'com.arello-mobile:moxy:0.4.3'
    compile 'com.arello-mobile:moxy-android:0.4.3'
    kapt 'com.arello-mobile:moxy-compiler:0.4.3'

and presenter in activity is null( what can be wrong?

References link

readme.md
References [RU] Moxy — реализация MVP под Android с щепоткой магии

Ведет на пример, который уже указан выше, а не на статью на habrahabr (?).

Кастомный MvpPresenter

Здравствуйте!
Очень хочется инжектить модели к пресентерам через BasePresenter, унаследовав его от MvpPresenter. (По аналогии с BaseActivity/BaseFragment). А из самих презентеров вызывать уже готовые модели.
Возможно ли это в Moxy?

How exactly does this work?

Let's take a simple login screen. We have LoginView

@StateStrategyType(value = AddToEndStrategy::class)
interface LoginView : MvpView {
    fun showProgress()
}

LoginActivity:

@InjectPresenter(type = PresenterType.LOCAL)
@JvmField
var mLoginPresenter: LoginPresenter? = null

// basic boilerplate ...

override fun showProgress() {
        contentContainer.visibility = View.GONE
        progressLoader.visibility = View.VISIBLE
        progressLoader.show()
    }

and a presenter:

@InjectViewState
open class LoginPresenter : MvpPresenter<LoginView>() {
    fun login() {
        viewState.showProgress()
    }
}

If I call mLoginPresenter.login() when I press login button my progressbar appears (ViewCommands are created for ViewState), but when I rotate the screen, it's shows login form. If I inspect it, it seems that the presenter does not survive state change and contains no ViewCommands afterwards to restore the state as a new instance is injected:

if (mViewCommands.isEmpty())
        {
            return;
        }

is always positive.

Tried Notelin app example, has the same problem - presenter does not survive. Is this behavior expected or am I not getting something?

MvpView with parameter "command"

Code generation makes wrong code if some method of MvpView contains parameter named "command". Code generation should be fixed.

Testing

Any suggestion on how to test a project using this library?

Android DataBinding

Android DataBinding хорошо уживается с Moxy?
Можно их комбинировать?

Injecting dependencies into presenter

I'am trying to find out proper way of injecting dependencies into presenter. Since passing dependencies in constructor is not an option we need to use some other mechanism. If we'll take a look at MoxySample, for example at SignInPresenter

  public class SignInPresenter extends MvpPresenter<SignInView> {
    @Inject
    Context mContext;
    @Inject
    GithubService mGithubService;

    public SignInPresenter() {
        GithubApp.getAppComponent().inject(this);
    }
        //...

we will see that injection is happening in constructor of presenter. But this line devaluates the whole point of DI process, since we are introducing unnecessary dependency from GithubApp. And also this prevents presenter from being tested properly.
Another place to call component's inject method would be from activity/fragment onCreate method but this would cause reinjecting dependencies each time activity or fragment is recreated, including orientation change, which is also not good. So can you suggest preferred way of passing dependencies?

ProGuard rules

I can't find any proguard rules for moxy. I use moxy 0.5.4 and after building with proguard @InjectPresenter returns null.
With this line -keep class * extends com.arellomobile.mvp.PresenterBinder it works. Does moxy need any additional rules?

Проблема с фрагментами

Здравствуйте!
Возникла проблема с использованием фрагментов. (при возврате через onBackPressed к прошлому фрагменту из стека)

Что происходит:

  1. Открываем фрагмент 1
  2. Открываем фрагмент 2
    при нажатии на кнопку назад - открывается старое состояние фрагмента 1, и сразу же возвращается на фрагмент 2.
    Долго не мог понять в чём проблема, пока не сделал то же самое в отдельном проекте. (где всё заработало)

MainActivity:

 @Override
   public void showNumberFragment() {
       getSupportFragmentManager()
               .beginTransaction()//first fragment in app
               .replace(R.id.ltContainer, NumberFragment.newInstance())
               .commit();
   }

   @Override
   public void showSmsKeyFragment() {
       getSupportFragmentManager()
               .beginTransaction()
               .replace(R.id.ltContainer, SmsKeyFragment.newInstance())
               .addToBackStack(null)
               .commit();
   }

MainPresenter

@InjectViewState
public class MainPresenter extends MvpPresenter<MainView> {

    //@formatter:off
    @Inject  RestApi restApi;
    @Inject  PreferenceHelper preferenceHelper;
    //@formatter:on

    public MainPresenter() {
        App.getAppComponent().inject(this);
    }

    public void showFragment() {
        if (preferenceHelper.isFirstRun()) {
            getViewState().showNumberFragment();
        }
    }

}

1 из фрагментов: (оба типичные)

public class SmsKeyFragment extends BaseFragment implements SmsKeyView {

    private static final int LAYOUT = R.layout.fragment_sms_key;

    //@formatter:off
    @InjectPresenter SmsKeyPresenter smsKeyPresenter;
    @BindView(R.id.btnOk) Button btnOk;
    @BindView(R.id.etSmsKey) EditText etSmsKey;
    @BindView(R.id.tvError) TextView tvError;
    @BindView(R.id.tvTimeCounter) TextView tvTimeCounter;
    //@formatter:on

    public static SmsKeyFragment newInstance() {
        SmsKeyFragment fragment = new SmsKeyFragment();
        Bundle args = new Bundle();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
                             final Bundle savedInstanceState) {

        View view = inflater.inflate(LAYOUT, container, false);
        ButterKnife.bind(this,view);
        setupListeners();
//        smsKeyPresenter.startTimer();
        return view;
    }

    private void setupListeners() {
        btnOk.setOnClickListener(v->smsKeyPresenter.onClickOk(etSmsKey.getText().toString()));
        etSmsKey.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                smsKeyPresenter.checkSmsKey(charSequence);
            }

            @Override
            public void afterTextChanged(Editable editable) {
            }
        });
    }


    @Override
    public void updateTimeCounter(String time) {
        getActivity().runOnUiThread(() -> tvTimeCounter.setText(time));
    }


    @Override
    public void onViewCreated(final View view, final Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

    @Override
    public void showMapFragment() {
        hideKeyboard();
        ((MainActivity) getActivity()).showMapFragment();
    }

    @Override
    public void activeOkButton() {
        // FIXME: 10.11.2016
    }

    @Override
    public void noActiveOkButton() {
        //// FIXME: 10.11.2016 
    }

    @Override
    public void goneError() {
        tvError.setVisibility(View.GONE);
    }

    @Override
    public void showError(String errorMessage) {
        tvError.setText(errorMessage);
        tvError.startAnimation(AnimationUtils.loadAnimation(getContext(),R.anim.error_transition));
        tvError.setVisibility(View.VISIBLE);
    }

}

Презентер такой же по формату как в MainActivity.

Moxy failed at screen rotation

Можно по-русски, да?
Здрасьте.
Как-то при повороте экрана не очень сохраняется state
как на эмуляторе (API-24), так и на зверьке (API-17).
Все на видео.
Причем в ланшафтном режиме кнопка "далее" тоже не переводит к следующему полю.
В чем может быть дело?
С уважением, ВВК

Android-apt most recent version support

Hi.
I am playing with your lib and see some strange behaivour when building from the command line using gradlew. Executing gradlew assembleDebug will fail if I have android-apt version 1.8 (most recent for now) declared. Stacktrace:

Caused by: java.lang.NoSuchFieldError: DEFAULT
        at com.arellomobile.mvp.compiler.MvpCompiler.process(MvpCompiler.java:85)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:793)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:722)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1700(JavacProcessingEnvironment.java:97)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1029)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1163)
        at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1108)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:824)
        at com.sun.tools.javac.main.Main.compile(Main.java:439)
        ... 79 more

Build from Android Studio's "Run" command is successfull every time.
Everything is fine when I switch android-apt to ver. 1.4.
P.S. Lib looks helpful - great job

Animate and Screen rotation

Здравствуйте!
При повороте экрана приложение вылетает без каких либо сообщений в лог.

LoginView

public interface LoginView extends MvpView {
    void showLoginScreen();
    void showRegisterScreen();
}

LoginPresenter

@InjectViewState
public class LoginPresenter extends MvpPresenter<LoginView> {
    public LoginPresenter() { }

    public void changeScreen(int screen) {
        if (screen==0){
            getViewState().showLoginScreen();
        }else{
            getViewState().showRegisterScreen();
        }
    }
}

ActivityLogin

public class ActivityLogin extends MvpAppCompatActivity implements LoginView {
    @InjectPresenter
    LoginPresenter pLoginPresenter;

    @Bind(R.id.tvBottomMessage_login) TextView tvBottomMessage_login;
    @Bind(R.id.tvBottomMessage_register) TextView tvBottomMessage_register;
    @Bind(R.id.rlLogin) View myViewLog;
    @Bind(R.id.rlRegister) View myViewReg;

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

        ButterKnife.bind(this);

        tvBottomMessage_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                pLoginPresenter.changeScreen(1);
            }
        });

        tvBottomMessage_register.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                pLoginPresenter.changeScreen(0);
            }
        });
    }

    @Override
    public void showLoginScreen() {
        int finalRadius2 = Math.max(myViewLog.getWidth(), myViewLog.getHeight());
        Animator anim = ViewAnimationUtils.createCircularReveal(myViewLog, myViewLog.getWidth() / 2, myViewLog.getHeight(), 0, finalRadius2);
        myViewReg.setZ(0);
        myViewLog.setZ(1);
        anim.start();
    }

    @Override
    public void showRegisterScreen() {
        int finalRadius2 = Math.max(myViewReg.getWidth(), myViewReg.getHeight());
        Animator anim = ViewAnimationUtils.createCircularReveal(myViewReg, myViewReg.getWidth() / 2, myViewReg.getHeight(), 0, finalRadius2);
        myViewReg.setZ(1);
        myViewLog.setZ(0);
        anim.start();
    }
}

Не могу понять, как сохранить текущий вид, для его последующего отображения после поворота экрана.

Inheriting in stabbed classes wrong!

AppCompatActivity shoud be extends from FragmentActivity.
FragmentActivity shoud be extends from Activity.
etc

it is important because some librarys expects

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) не спасает.

Спасибо!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.