Giter Club home page Giter Club logo

arthur3486 / android-mvvm Goto Github PK

View Code? Open in Web Editor NEW
110.0 2.0 22.0 38.16 MB

Android library designed to greatly simplify the implementation process of an MVVM-based application by providing all the means necessary to solve the common problems and avoid the annoying boilerplate code.

License: Apache License 2.0

Kotlin 97.91% Java 2.09%
android android-mvvm android-mvvm-architecture clean-architecture mvvm dagger dagger2 rxjava rxjava2 solid

android-mvvm's Introduction

Android MVVM Library + Comprehensive Demo Application

Android library designed to greatly simplify the implementation process of an MVVM-based application by providing all the means necessary to solve the common problems and avoid the annoying boilerplate code.

The library is accompanied by a comprehensive Demo Application that is built around MVVM and Clean Architecture concepts. The Demo Application utilizes such popular libraries as: RxJava, Dagger2, Android Navigation Architecture Component, OkHttp, Retrofit, Room, Glide.

Android MVVM Library will make the implementation of your MVVM-based application a trivial task thus allowing you to spend more time focusing on other important things.

Download License Platform Android Arsenal

Contents

Demo

Marvel Universe Application is an application built around MVVM and Clean Architecture concepts, as well as the data provided by the Marvel API. The application allows you to browse through the Marvel comics, events and characters; each of the aforementioned entities is accompanied by a corresponding detailed overview screen, which gives you even more insight into the Marvel Universe.

Screenshots

Application Architecture

Application Architecture

Getting Started

Prerequisites

1. Make sure that you've added the jcenter() repository to your top-level build.gradle file.

buildscript {
    //...
    repositories {
        //...
        jcenter()
    }
    //...
}

2. Enable the jetifier and androidX support in the top-level gradle.properties file.

//...
android.enableJetifier=true
android.useAndroidX=true
//....

3. Update your compileSdkVersion in the module-level build.gradle file to 29+.

//...
android {
    //...
    compileSdkVersion 29
    //...
}
//...

4. Enable the Data Binding in the module-level build.gradle file.

//...
android {
    //...
    dataBinding {
        enabled true
    }
    //...
}
//...

5. Replace your com.android.support.appcompat.* dependency with the new androidx.appcompat.* alternative.

//...
dependencies {
    //...
    implementation "androidx.appcompat:appcompat:1.0.2"
    //...
}
//...

6. Add the Android Lifecycle (ViewModel), RxJava and RxBus dependencies to the module-level build.gradle file.

//...
dependencies {
    //...
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.0.0"
    implementation "io.reactivex.rxjava2:rxjava:2.2.12"
    implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
    implementation "com.arthurivanets.rxbus:rxbus:1.1.0"
    //...
}
//...

Android MVVM Dependencies

The basic implementation must include the core module

Latest version: Download

implementation "com.arthurivanets.mvvm:mvvm-core:X.Y.Z"

Which should be added to your module-level build.gradle file.

ext {
    //...
    androidMvvmLibraryVersion = "1.3.1"
}

dependencies {
    //...
    implementation "com.arthurivanets.mvvm:mvvm-core:$androidMvvmLibraryVersion"
}

After that you can proceed with further implementation.

See: Basic Implementation, Dagger Based Implementation, Navigation Component Based Implementation, Navigation Component and Dagger Based Implementation

Modules

The library is comprised of several modules, namely:

The mvvm-core module is a core module the other modules depend on. It provides all the means necessary to create the MVVM-based Fragments and Activities, as well the corresponding ViewModels. (See: MvvmFragment, MvvmActivity, BaseViewModel, AbstractViewModel, Command, ViewState, Route)

The mvvm-dagger module is a module that provides the MvvmActivity and MvvmFragment implementations that automatically handle the injection of the Dagger DI dependencies.

The mvvm-navigation module is a module that provides the MvvmActivity and MvvmFragment implementations with built-in support for the Android Navigation Component based navigation.

mvvm-navigation-dagger module is a module that provides the MvvmActivity and MvvmFragment implementations that have both the built-in support for the Android Navigation Component based navigation and automatic handling of the injection of the Dagger DI dependencies.

Basic Implementation

The basic implementation consists of 5 simple steps, namely:

  1. Creation of the ViewModel
  2. Creation of the ViewModel-specific View States & Commands
  3. Creation of the application screen routes
  4. Creation of the layout.xml for the Activity/Fragment
  5. Implementation of the Activity/Fragment

So, let's start with the creation of the ViewModel for our Activity and/or Fragment.

SimpleViewModel.kt [contract] (click to expand)

interface SimpleViewModel : BaseViewModel {

    // The rest of your observable fields and event propagation methods should be defined here

}

The ViewModel contract should implement the BaseViewModel interface.

SimpleViewModelImpl.kt [concrete implementation] (click to expand)

class SimpleViewModelImpl : AbstractViewModel(), SimpleViewModel {

    // Your concrete implementation...

}

The concrete implementation of the ViewModel should extend the AbstractViewModel class and implement the corresponding contract interface.


Then, create the ViewModel-specific View States & Commands.

GeneralViewStates.kt (click to expand)

sealed class GeneralViewStates<T>(payload : T? = null) : ViewState<T>(payload) {

    class Initial : GeneralViewStates<Unit>()

    class Loading<T>(payload : T? = null) : GeneralViewStates<T>(payload)

    class Success<T>(payload : T? = null) : GeneralViewStates<T>(payload)

    class Error<T>(payload : T? = null) : GeneralViewStates<T>(payload)

    // The rest of your View State go here...

}

The implementation of the ViewModel-specific View States should be based upon the ViewState class.

GeneralViewModelCommands.kt (click to expand)

sealed class GeneralViewModelCommands<T>(payload : T? = null) : Command<T>(payload) {

    class ShowToast(text : String) : GeneralViewModelCommands<String>(text)

    class RestartApplication : GeneralViewModelCommands<Unit>()

    // The rest of your ViewModel Commands go here...

}

The implementation of the ViewModel-specific Commands should be based upon the Command class.


Then, create the application screen routes.

MarvelRoutes.kt (click to expand)

sealed class MarvelRoutes<T>(payload : T? = null) : Route<T>(payload) {

    class CharacterInfoScreen(character : Character) : MarvelRoutes<Character>(character)

    class ComicsInfoScreen(comics : Comics) : MarvelRoutes<Comics>(comics)

    class EventInfoScreen(event : Event) : MarvelRoutes<Event>(event)

    // The rest of your Application Routes go here...

}

The implementation of the Application Screen Routes should be based upon the Route class.


After that, let's create the layout.xml files for both our Activity and Fragment.

activity_simple_mvvm.xml + fragment_simple_mvvm.xml (click to expand)

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- Data-binding-related -->

    <data>

        <variable
            name="viewModel"
            type="com.yourapplication.sample.SimpleViewModel"/>

    </data>

    <!-- The Content Layout -->
    <!-- Your content layout goes here... -->

</layout>


Finally, let's implement the MVVM-based Activity and Fragment.

SimpleMvvmActivity.kt (click to expand)

import com.arthurivanets.mvvm.MvvmActivity

class SimpleMvvmActivity : MvvmActivity<ActivitySimpleMvvmBinding, SimpleViewModel>() {

    private lateinit var localViewModel : SimpleViewModel

    override fun injectDependencies() {
        // Initialize your View Model here...
        localViewModel = SimpleViewModelImpl()
    }

    // The rest of the Activity Initialization goes here...

    override fun onRegisterObservables() {
        // Register your ViewModel's observable fields here...
    }

    override fun onHandleCommand(command : Command<*>) {
        // handle the ViewModel-specific command here... (e.g. Restart the Application, Show Toast, etc.)
    }

    override fun onViewStateChanged(state : ViewState<*>) {
        // handle the View State Change here... (adjust your UI correspondingly)
    }

    override fun onRoute(route : Route<*>) {
        // handle the Application Route here... (navigate to the corresponding screen)
    }

    override fun getLayoutId() : Int {
        return R.layout.activity_simple_mvvm
    }

    override fun getBindingVariable() : Int {
        return BR.viewModel
    }

    override fun getViewModel() : SimpleViewModel {
        return localViewModel
    }

}

The implementation of the MVVM Activity should be based upon the Core MvvmActivity class.

SimpleMvvmFragment.kt (click to expand)

import com.arthurivanets.mvvm.MvvmFragment

class SimpleMvvmFragment : MvvmFragment<FragmentSimpleMvvmBinding, SimpleViewModel>() {

    private lateinit var localViewModel : SimpleViewModel

    override fun injectDependencies() {
        // Initialize your View Model here...
        localViewModel = SimpleViewModelImpl()
    }

    // The rest of the Fragment Initialization goes here...

    override fun onRegisterObservables() {
        // Register your ViewModel's observable fields here...
    }

    override fun onHandleCommand(command : Command<*>) {
        // handle the ViewModel-specific command here... (e.g. Restart the Application, Show Toast, etc.)
    }

    override fun onViewStateChanged(state : ViewState<*>) {
        // handle the View State Change here... (adjust your UI correspondingly)
    }

    override fun onRoute(route : Route<*>) {
        // handle the Application Route here... (navigate to the corresponding screen)
    }

    override fun getLayoutId() : Int {
        return R.layout.fragment_simple_mvvm
    }

    override fun getBindingVariable() : Int {
        return BR.viewModel
    }

    override fun getViewModel() : SimpleViewModel {
        return localViewModel
    }

}

The implementation of the MVVM Fragment should be based upon the Core MvvmFragment class.


The MvvmActivity, MvvmFragment and AbstractViewModel classes provide many convenience methods for dealing with the lifecycle of the ObservableField subscriptions and Rx disposbles, so it's definitely a good idea to look through the implementations in order to familiarize yourself with the available APIs.

See: MvvmActivity, MvvmFragment, BaseViewModel, AbstractViewModel, Command, ViewState, Route, GeneralViewStates, MarvelRoutes

Dagger Based Implementation

The Dagger-based implementation process is almost identical to the one of the Basic Implementation, the only thing that's different here is the fact that you need to use the MvvmActivity and MvvmFragment provided by the mvvm-dagger module instead of the ones coming from the mvvm-core module.

SimpleMvvmActivity.kt (click to expand)

import com.arthurivanets.mvvm.dagger.MvvmActivity

class SimpleMvvmActivity : MvvmActivity<ActivitySimpleMvvmBinding, SimpleViewModel>() {

    @Inject
    private lateinit var localViewModel : SimpleViewModel

    // The rest of the Activity Initialization goes here...

    override fun onRegisterObservables() {
        // Register your ViewModel's observable fields here...
    }

    override fun onHandleCommand(command : Command<*>) {
        // handle the ViewModel-specific command here... (e.g. Restart the Application, Show Toast, etc.)
    }

    override fun onViewStateChanged(state : ViewState<*>) {
        // handle the View State Change here... (adjust your UI correspondingly)
    }

    override fun onRoute(route : Route<*>) {
        // handle the Application Route here... (navigate to the corresponding screen)
    }

    override fun getLayoutId() : Int {
        return R.layout.activity_simple_mvvm
    }

    override fun getBindingVariable() : Int {
        return BR.viewModel
    }

    override fun getViewModel() : SimpleViewModel {
        return localViewModel
    }

}

The implementation of the MVVM Activity should be based upon the Dagger MvvmActivity class.

SimpleMvvmFragment.kt (click to expand)

import com.arthurivanets.mvvm.dagger.MvvmFragment

class SimpleMvvmFragment : MvvmFragment<FragmentSimpleMvvmBinding, SimpleViewModel>() {

    @Inject
    private lateinit var localViewModel : SimpleViewModel

    // The rest of the Fragment Initialization goes here...

    override fun onRegisterObservables() {
        // Register your ViewModel's observable fields here...
    }

    override fun onHandleCommand(command : Command<*>) {
        // handle the ViewModel-specific command here... (e.g. Restart the Application, Show Toast, etc.)
    }

    override fun onViewStateChanged(state : ViewState<*>) {
        // handle the View State Change here... (adjust your UI correspondingly)
    }

    override fun onRoute(route : Route<*>) {
        // handle the Application Route here... (navigate to the corresponding screen)
    }

    override fun getLayoutId() : Int {
        return R.layout.fragment_simple_mvvm
    }

    override fun getBindingVariable() : Int {
        return BR.viewModel
    }

    override fun getViewModel() : SimpleViewModel {
        return localViewModel
    }

}

The implementation of the MVVM Fragment should be based upon the Dagger MvvmFragment class.

See: MvvmActivity, MvvmFragment

Navigation Component Based Implementation

The Navigation Component based implementation process has many things in common with the Basic Implementation; the differences are shown in the code snippets below.

activity_host.xml (click to expand)

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- Data-binding-related -->

    <data>

        <variable
            name="viewModel"
            type="com.yourapplication.sample.StubViewModel"/>

    </data>

    <!-- The Actual Layout -->

    <com.google.android.material.internal.ScrimInsetsFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <fragment
            android:id="@+id/nav_host_fragment"
            android:name="com.arthurivanets.mvvm.navigation.MvvmNavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/your_navigation_graph"/>

    </com.google.android.material.internal.ScrimInsetsFrameLayout>

</layout>

The MvvmNavHostFragment should be used as a Navigation Host Fragment of the Host Activity.

HostActivity.kt (click to expand)

import com.arthurivanets.mvvm.navigation.MvvmActivity

class HostActivity : MvvmActivity<ActivityHostBinding, StubViewModel>() {

    private var localViewModel : StubViewModel

    override fun injectDependencies() {
        localViewModel = StubViewModelImpl()
    }

    override fun getLayoutId() : Int {
        return R.layout.activity_host
    }

    override fun getBindingVariable() : Int {
        return BR.viewModel
    }

    override fun getViewModel() : HostActivityViewModel {
        return localViewModel
    }

    override fun getNavigationGraphId() : Int {
        return R.navigation.your_navigation_graph
    }

}

The implementation of the Host Activity should be based upon the Navigation MvvmActivity class.

SimpleMvvmFragment.kt (click to expand)

import com.arthurivanets.mvvm.navigation.MvvmFragment

class SimpleMvvmFragment : MvvmFragment<FragmentSimpleMvvmBinding, SimpleViewModel>() {

    private lateinit var localViewModel : SimpleViewModel

    override fun injectDependencies() {
        // Initialize your View Model here...
        localViewModel = SimpleViewModelImpl()
    }

    // The rest of the Fragment Initialization goes here...

    override fun onRegisterObservables() {
        // Register your ViewModel's observable fields here...
    }

    override fun onHandleCommand(command : Command<*>) {
        // handle the ViewModel-specific command here... (e.g. Restart the Application, Show Toast, etc.)
    }

    override fun onViewStateChanged(state : ViewState<*>) {
        // handle the View State Change here... (adjust your UI correspondingly)
    }

    override fun onRoute(route : Route<*>) {
        // handle the Application Route here... (navigate to the corresponding screen)
    }

    override fun getLayoutId() : Int {
        return R.layout.fragment_simple_mvvm
    }

    override fun getBindingVariable() : Int {
        return BR.viewModel
    }

    override fun getViewModel() : SimpleViewModel {
        return localViewModel
    }

}

The implementation of the MVVM Fragment should be based upon the Navigation MvvmFragment class.

See: MvvmActivity, MvvmFragment, MvvmNavHostFragment

Navigation Component and Dagger Based Implementation

Shares many implementation-specific aspects with the previously described implementation types and is used in the Demo Application.

See: MvvmActivity, MvvmFragment

Compilation

In order to compile the app module you need to obtain the PUBLIC_API_KEY and PRIVATE_API_KEY from the Marvel API portal, which should be saved in either global gradle.properties file or the project-specific one thereafter.

gradle.properties

marvelApiPublicKey=PUBLIC_API_KEY
marvelApiPrivateKey=PRIVATE_API_KEY

Contribution

See the CONTRIBUTING.md file.

Hall of Fame

Using Android MVVM Library in your app and want it to get listed here? Email me at [email protected]!

License

Android MVVM Library is licensed under the Apache 2.0 License.

android-mvvm's People

Contributors

arthur3486 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

android-mvvm's Issues

(BUG android-mvvm version 1.2.0 ) Desktop options do not appear

Project Information

Expected behavior

when I try to open the application All options should appear for user

Actual behavior

When I open the application, no options appear and the application is buffering.

How to reproduce

  • Download the application

  • open the application

  • Note the Error

  • Browser/App version: 1.2.0

  • Operating system: 6.0

Recording Of The Bug

20190727_154316

java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener"

Hi, I see a bug during start your project. Here the stack trace:
Rejecting re-init on previously-failed class java.lang.Class<androidx.core.view.ViewCompat$OnUnhandledKeyEventListenerWrapper>: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/view/View$OnUnhandledKeyEventListener; at void androidx.core.view.ViewCompat.setOnApplyWindowInsetsListener(android.view.View, androidx.core.view.OnApplyWindowInsetsListener) (ViewCompat.java:2203) at android.view.ViewGroup androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:637) at void androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518) at void androidx.appcompat.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:466) at void androidx.appcompat.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:140) at androidx.databinding.ViewDataBinding androidx.databinding.DataBindingUtil.setContentView(android.app.Activity, int, androidx.databinding.DataBindingComponent) (DataBindingUtil.java:303) at androidx.databinding.ViewDataBinding androidx.databinding.DataBindingUtil.setContentView(android.app.Activity, int) (DataBindingUtil.java:284) at void com.arthurivanets.mvvm.MvvmActivity.initDataBinding() (MvvmActivity.kt:134) at void com.arthurivanets.mvvm.MvvmActivity.onCreate(android.os.Bundle) (MvvmActivity.kt:61) at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:6679) at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1118) at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2618) at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2726) at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1) at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1477) at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102) at void android.os.Looper.loop() (Looper.java:154) at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6119) at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2) at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:886) at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:776) Caused by: java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener" on path: DexPathList[[zip file "/data/app/com.arthurivanets.sample-1/base.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_dependencies_apk.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_slice_0_apk.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_slice_1_apk.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_slice_2_apk.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_slice_3_apk.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_slice_4_apk.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_slice_5_apk.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_slice_6_apk.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_slice_7_apk.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_slice_8_apk.apk", zip file "/data/app/com.arthurivanets.sample-1/split_lib_slice_9_apk.apk"],na at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:56) at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:380) at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312) at void androidx.core.view.ViewCompat.setOnApplyWindowInsetsListener(android.view.View, androidx.core.view.OnApplyWindowInsetsListener) (ViewCompat.java:2203) at android.view.ViewGroup androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:637) at void androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518) at void androidx.appcompat.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:466) at void androidx.appcompat.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:140) at androidx.databinding.ViewDataBinding androidx.databinding.DataBindingUtil.setContentView(android.app.Activity, int, androidx.databinding.DataBindingComponent) (DataBindingUtil.java:303) at androidx.databinding.ViewDataBinding androidx.databinding.DataBindingUtil.setContentView(android.app.Activity, int) (DataBindingUtil.java:284) at void com.arthurivanets.mvvm.MvvmActivity.initDataBinding() (MvvmActivity.kt:134) at void com.arthurivanets.mvvm.MvvmActivity.onCreate(android.os.Bundle) (MvvmActivity.kt:61) at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:6679) at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1118) at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2618) at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2726) at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1) at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1477) at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102) at void android.os.Looper.loop() (Looper.java:154) at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6119) at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2) at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:886) at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:776) I/ViewConfigCompat: Could not find method getScaledScrollFactor() on ViewConfiguration

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.