Giter Site home page Giter Site logo

akshaychordiya / news Goto Github PK

View Code? Open in Web Editor NEW
840.0 42.0 163.0 2.96 MB

A sample News 🗞 app built using Modern Android Development [Architecture Components, Coroutines, Retrofit, Room, Kotlin, Dagger]

License: MIT License

Kotlin 100.00%
kotlin architecture-guidelines android android-architecture-components android-architecture architecture-components room viewmodel newsapi retrofit2 coroutines kotlin-flow dagger2

news's Introduction

News App 🗞

GitHub license

News App is a simple news app 🗞️ which uses NewsAPI to fetch top news headlines from the API. The main aim of this app is to be a leading example of how to build Modern Android applications for all Android Developers

The codebase focuses 👓 on following key things:

  • Code structuring, style and comments
  • Dependency injection 🗡
  • Offline first ✈️
  • Kotlin + Coroutines
  • And tests 🛠
  • Emojis (ofcourse) 😛

The idea is to keep the app super simple while demonstrating new libraries and tools which makes it easier to build high quality Android applications.

NewsApp Main Page

Development Setup 🖥

You will require latest version of Android Studio 3.0 (or newer) to be able to build the app

API key 🔑

You'll need to provide API key to fetch the news from the News Service (API). Currently the news is fetched from NewsAPI

  • Generate an API key (It's only 2 steps!) from NewsAPI
  • Create new file named -> credentials.properties in our project root folder
  • Add the API key as shown below [Make sure to keep the double quotes]:
    NEWS_API_KEY = "<INSERT_YOUR_API_KEY>"
  • Build the app
  • Enjoyyyyy 🎉

Libraries and tools 🛠

News App uses libraries and tools used to build Modern Android application, mainly part of Android Jetpack 🚀

Architecture

The app uses MVVM [Model-View-ViewModel] architecture to have a unidirectional flow of data, separation of concern, testability, and a lot more.

Read more:

Architecture

Dependency Graph 🔪

The following diagram shows the dependency graph of the app.

News App Dependency Graph

Generated by Daggraph


Learn Architecture Components

Trying to learn the new Architecture Components. I have wrote a series of articles to understand Android Architecture Components. Feel free to check it out to learn more.

Extra - Caster.io Course and Podcast

Testing

The architecture components are highly testable. Following table shows how to test various parts of the app (cheatsheet for testing architecture component)

Component Test Mock
UI Espresso ViewModel
ViewModel JUnit Repository
Repository JUnit DAO and WebService
DAO Instrumented -
WebService Instrumented MockWebServer

Contributing

Please read CONTRIBUTING.md for contributions.

License

The MIT License (MIT)

Copyright (c) 2017 Akshay Chordiya

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.

news's People

Contributors

akshaychordiya avatar ezike avatar patilshreyas avatar pranaypatel512 avatar rohiththammaiah avatar swapnilmadavi avatar veerhan 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

news's Issues

rss news

Hola!, en vez de la api, quiero usar un rss de un sitio, para que muestre noticias de ese sitio

Failed to resolve: support-vector-drawable

this is steps to reproduce:

  1. use android studio 3.2.1
  2. download the project, extract, & open it
  3. add news_key_api to all-projects gradle.properties
  4. build it
  5. download build tools version 28.0.0 rc2 because it is not yet exists in my android studio
  6. rebuild again
  7. error Failed to resolve: support-vector-drawable. If I click "Open file", it will open build.gradle (app).

please help.. I can't even reach to see the project running in emulator

Replace Dagger with Koin

@AkshayChordiya
We can replace Dagger with Koin for ease of understanding and since the project is Kotlin first, I think koin would be a perfect fit.
Reference - https://insert-koin.io

Let me know if this is something that you want for the project, I am willing to give it a try and add it.

help

I am runnig app this error : Program type already present: android.support.v4.os.ResultReceiver
Message{kind=ERROR, text=Program type already present: android.support.v4.os.ResultReceiver, sources=[Unknown source file], tool name=Optional.of(D8)}
what is this akshay please help me

Replace Glide with Coil

Since the repository is heavy on Kotlin and coroutines, we can continue the trend by replacing Glide dependency with Coil which is Kotlin and coroutines first and is much light weight than Glide and doesn't use annotation processing 🎉

Suggested by @annshsingh

Implement news details screen

  • Implement a new screen / activity showing details about the clicked news article
  • Try to use Jetpack compose for the UI

How to handle ViewState.error

Hello, any tips how to handle ViewState.error? I tried
emit(ViewState.error("Error"))
But I dont know how to stop the flow there

Setup CI and code coverage bot

Setup CI integration most likely using GitHub actions to check if the build builds successfully + tests in the branch and also on every PR.
It would be nice to also integrate code coverage plugin to know the code coverage 🎉

How to get updated news data.

I have forked your arch-news repo and ran the code.

I understood how everything works including the Network bound resource.

I am debugging using the android debugger.... (Let me know if I am wrong)

*First it checks if it can load from db.
*Then since the data is not present in the db it goes to the should fetch method where it returns empty.
*Then since no data is present it creates a network call.
*Then it saves the call result in saveCallResult.
*Then it again loads from db and shows the results.

Then everytime it loads the data from the db. Now if the news articles are updated. News results are not observed and hence not shown. Its only loaded from the database.

How can we periodically observe for new data and then update it in the database.

Caused by: java.lang.RuntimeException: Cannot create an instance of class com.akshay.newsapp.news.ui.viewmodel.NewsArticleViewModel

gettting below error at first launch after import in to android studio

2020-02-27 15:16:26.804 23096-23096/com.akshay.newsapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.akshay.newsapp, PID: 23096
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.akshay.newsapp/com.akshay.newsapp.news.ui.activity.NewsActivity}: java.lang.RuntimeException: Cannot create an instance of class com.akshay.newsapp.news.ui.viewmodel.NewsArticleViewModel
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2952)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3087)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1817)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6746)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.RuntimeException: Cannot create an instance of class com.akshay.newsapp.news.ui.viewmodel.NewsArticleViewModel
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:278)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.akshay.newsapp.news.ui.activity.NewsActivity$newsArticleViewModel$2.invoke(NewsActivity.kt:50)
at com.akshay.newsapp.news.ui.activity.NewsActivity$newsArticleViewModel$2.invoke(NewsActivity.kt:18)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at com.akshay.newsapp.news.ui.activity.NewsActivity.getNewsArticleViewModel(Unknown Source:7)
at com.akshay.newsapp.news.ui.activity.NewsActivity.onCreate(NewsActivity.kt:39)
at android.app.Activity.performCreate(Activity.java:7144)
at android.app.Activity.performCreate(Activity.java:7135)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2932)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3087) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1817) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:193) 
at android.app.ActivityThread.main(ActivityThread.java:6746) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
Caused by: java.lang.InstantiationException: java.lang.Class<com.akshay.newsapp.news.ui.viewmodel.NewsArticleViewModel> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:278) 
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) 
at com.akshay.newsapp.news.ui.activity.NewsActivity$newsArticleViewModel$2.invoke(NewsActivity.kt:50) 
at com.akshay.newsapp.news.ui.activity.NewsActivity$newsArticleViewModel$2.invoke(NewsActivity.kt:18) 
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) 
at com.akshay.newsapp.news.ui.activity.NewsActivity.getNewsArticleViewModel(Unknown Source:7) 
at com.akshay.newsapp.news.ui.activity.NewsActivity.onCreate(NewsActivity.kt:39) 
at android.app.Activity.performCreate(Activity.java:7144) 
at android.app.Activity.performCreate(Activity.java:7135) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2932) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3087) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1817) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:193) 
at android.app.ActivityThread.main(ActivityThread.java:6746) 
at java.lang.reflect.Method.invoke(Native Method)

javax annotation does not exist

I downloaded the master project and tried to build after adding the credentials file. There is an error:

kapt/debug/com/akshay/newsapp/ui/viewmodel/NewsArticleViewModel_Factory.java:5: error: package javax.annotation.processing does not exist import javax.annotation.processing.Generated;

I tried following google/dagger#1339 to add Java 1.8 as compileOptions. Also tried to add java 1.8 to gradle.properties. These didn't resolve the issue. I should be using Java 1.8 by default everywhere.

What worked in the end was adding extra dependency: compileOnly 'com.github.pengrad:jdk9-deps:1.0'

edit:
This fix made the build work. Seems like a Dagger issue

Two Incorrect Configurations found in app/build.gradle

  1. implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion" needs to be testImplementation. As for right now, it is very unneeded libraries because it wouldn't break anything.

  2. implementation "androidx.arch.core:core-testing:$lifecycleVersion" needs to be testImplementation too.

NetworkBoundResource.asFlow() is called multiple times

After 5 seconds of no active observers for NewsArticleViewModel.newsArticles (device locked) and NewsActivity re-observe the newsArticles (device unlocked), NetworkBoundResource.asFlow() is called again.

If I change the emitAll(loadFromDb().map { ViewState.success(it) }) into emit(loadFromDb().map { ViewState.success(it) }.first()), NetworkBoundResource.asFlow() is not called.

Error while Gradle build

Could not get unknown property 'NEWS_API_KEY' for ProductFlavor_Decorated{name=main, dimension=null, minSdkVersion=DefaultApiVersion{mApiLevel=15, mCodename='null'}, targetSdkVersion=null, renderscriptTargetApi=null, renderscriptSupportModeEnabled=null, renderscriptSupportModeBlasEnabled=null, renderscriptNdkModeEnabled=null, versionCode=1, versionName=1.0, applicationId=com.akshay.newsapp, testApplicationId=null, testInstrumentationRunner=android.support.test.runner.AndroidJUnitRunner, testInstrumentationRunnerArguments={}, testHandleProfiling=null, testFunctionalTest=null, signingConfig=null, resConfig=null, mBuildConfigFields={}, mResValues={}, mProguardFiles=[], mConsumerProguardFiles=[], mManifestPlaceholders={}, mWearAppUnbundled=null} of type com.android.build.gradle.internal.dsl.ProductFlavor. Open File

Loading progress won't show for the first run of the app.

Based on my understanding of the NetworkBoundResource it looks like when the app will start for the first time, loading progress won't appear and the user will see a blank screen.

Here is why:

    fun asFlow() = flow {
        emit(ViewState.loading())

        val dbValue = loadFromDb().first()
        if (shouldFetch(dbValue)) {
            emit(ViewState.success(dbValue))
            try {
                val apiResponse = fetchFromNetwork()
                when {
                    apiResponse.isSuccessful && apiResponse.body() != null -> {
                        apiResponse.body()?.let { saveNetworkResult(it) }
                        emitAll(loadFromDb().map { ViewState.success(it) })
                    }
                    else -> {
                        emit(ViewState.error(apiResponse.message()))
                    }
                }
            } catch (e: Exception) {
                emit(ViewState.error("Unable to fetch from network"))
            }
        } else {
            emitAll(loadFromDb().map { ViewState.success(it) })
        }
    }

The shouldFetch() doesn't respect dbValue's actual value.

At the first start, this will be empty. However, code will immediately emit an Empty success state whereas it is actually still loading items from the network.

App only displays a blank screen

I tried running your project but all I get is a blank screen.

Here are the logs,

03-03 21:43:28.318 10149-10149/? I/art: Not late-enabling -Xcheck:jni (already on)
03-03 21:43:28.318 10149-10149/? W/art: Unexpected CPU variant for X86 using defaults: x86
03-03 21:43:28.334 10149-10156/? I/art: Debugger is no longer active
03-03 21:43:28.334 10149-10156/? I/art: Starting a blocking GC Instrumentation
03-03 21:43:28.439 10149-10149/? I/art: Starting a blocking GC AddRemoveAppImageSpace
03-03 21:43:28.563 10149-10149/? W/System: ClassLoader referenced unknown path: /data/app/com.akshay.newsapp-1/lib/x86
03-03 21:43:28.568 10149-10149/? I/InstantRun: starting instant run server: is main process
03-03 21:43:28.591 10149-10149/? D/DebugDB: Open http://0.0.0.0:8081 in your browser
03-03 21:43:28.633 10149-10149/? W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
03-03 21:43:28.743 10149-10149/? D/NetworkSecurityConfig: No Network Security Config specified, using platform default
03-03 21:43:28.767 10149-10149/? D/Main: Res = Resource(status=LOADING, data=null, message=null)
03-03 21:43:28.767 10149-10149/? D/Main: Data = null
03-03 21:43:28.807 10149-10149/? D/Main: Res = Resource(status=LOADING, data=[], message=null)
03-03 21:43:28.807 10149-10149/? D/Main: Data = []
                                         
                                         [ 03-03 21:43:28.824 10149:10175 D/         ]
                                         HostConnection::get() New Host Connection established 0xa11ab300, tid 10175
03-03 21:43:28.825 10149-10175/? I/OpenGLRenderer: Initialized EGL, version 1.4
03-03 21:43:28.825 10149-10175/? D/OpenGLRenderer: Swap behavior 1
03-03 21:43:28.825 10149-10175/? W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
03-03 21:43:28.825 10149-10175/? D/OpenGLRenderer: Swap behavior 0
03-03 21:43:28.833 10149-10175/? D/EGL_emulation: eglCreateContext: 0x9caf8e40: maj 2 min 0 rcv 2
03-03 21:43:28.849 10149-10175/? D/EGL_emulation: eglMakeCurrent: 0x9caf8e40: ver 2 0 (tinfo 0x9caabc30)
03-03 21:43:28.870 10149-10149/? W/art: Before Android 4.1, method int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
03-03 21:43:28.875 10149-10175/? D/EGL_emulation: eglMakeCurrent: 0x9caf8e40: ver 2 0 (tinfo 0x9caabc30)
03-03 21:43:28.944 10149-10175/? D/EGL_emulation: eglMakeCurrent: 0x9caf8e40: ver 2 0 (tinfo 0x9caabc30)

The app requests the news to the network, but it never updates with the proper data.

Can anyone double check if it's working?

Thanks

Iran

وزارت دفاع در توییتر نوشت:

🔻 دبیر شورای عالی امنیت ملی در دیدار رئیس پارلمان عراق گفت: با اقتدار به هرگونه اقدامی که بخواهد به امنیت ایران و منطقه آسیب وارد کند، به سرعت و با قاطعیت پاسخ می‌دهیم.
#عراق #شمخانی #حلبوسی

ارسال شده از اپلیکیشن توییتنا

#توییتنا #توییتر_فارسی #tweetna
Web: www.Tweetna.ir
Telegram: @tweetna
Instagram: @tweetna.ir

خبرگزاری توییتنا (Tweet News Agency)

http://cdn1.tweetna.ir/static/media/tweets/a505352ec66011ec92b10050564490a3.jpg

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.