-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
*.iml | ||
.gradle | ||
/local.properties | ||
/.idea/caches | ||
/.idea/libraries | ||
/.idea/modules.xml | ||
/.idea/workspace.xml | ||
/.idea/navEditor.xml | ||
/.idea/assetWizardSettings.xml | ||
.DS_Store | ||
/build | ||
/captures | ||
.externalNativeBuild | ||
.cxx | ||
local.properties |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
![Imgur](https://imgur.com/KSZEQFE.gif) | ||
# News App | ||
The NEWS application fetched the news and displays on the screen in either list or grid view. The user can click and see the detailed news in nexr screen. | ||
|
||
## App use case | ||
- Fetch news and show in List or grid. There is an option to change view from list to grid. | ||
- Clicking on the a news takes the user to the details page | ||
- Reaching to the end of the news list, more results should be downloaded. | ||
|
||
## App Architecture | ||
![Imgur](https://imgur.com/1HCtlJo.jpg) | ||
The architecture used for this application is MVVM. The activity uses viewModel functions to call API and fetch data via a repository. | ||
The data is pushed to a live data variable which is being observed in the activity class. | ||
Once the changes are detected, the UI is updated. | ||
|
||
Components used: | ||
Hilt for Dependency injection | ||
Coroutines for web service calls | ||
Data Binding for setting data in details class | ||
|
||
## Third Party Libraries | ||
The following libraries are used: | ||
- Retrofit: for calling APIs. | ||
- SDP intuit: to support multiple screen avoiding the dimens files. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
plugins { | ||
id 'com.android.application' | ||
id 'kotlin-android' | ||
id 'kotlin-kapt' | ||
id 'kotlin-android-extensions' | ||
id 'dagger.hilt.android.plugin' | ||
} | ||
|
||
android { | ||
compileSdkVersion 30 | ||
buildToolsVersion "30.0.3" | ||
|
||
dataBinding { | ||
enabled = true | ||
} | ||
|
||
defaultConfig { | ||
applicationId "com.suki.newsapp" | ||
minSdkVersion 24 | ||
targetSdkVersion 30 | ||
versionCode 1 | ||
versionName "1.0" | ||
|
||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||
} | ||
|
||
buildTypes { | ||
release { | ||
minifyEnabled false | ||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | ||
} | ||
} | ||
compileOptions { | ||
sourceCompatibility JavaVersion.VERSION_1_8 | ||
targetCompatibility JavaVersion.VERSION_1_8 | ||
} | ||
kotlinOptions { | ||
jvmTarget = '1.8' | ||
} | ||
} | ||
|
||
def room_version = "2.2.5" | ||
def sdp_version = "1.0.6" | ||
def hilt_android = "2.28.1-alpha" | ||
def hilt_lifecycle = "1.0.0-alpha01" | ||
def activity_ktx_version = "1.2.3" | ||
def lifecycle_ktx_version = "2.3.1" | ||
def timeago_version = "4.0.3" | ||
def mp_chart_version = "v3.1.0" | ||
def paging_version = "2.1.2" | ||
|
||
dependencies { | ||
|
||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" | ||
implementation 'androidx.core:core-ktx:1.5.0' | ||
implementation 'androidx.appcompat:appcompat:1.3.0' | ||
implementation 'com.google.android.material:material:1.3.0' | ||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' | ||
|
||
testImplementation 'junit:junit:4.+' | ||
androidTestImplementation 'androidx.test.ext:junit:1.1.2' | ||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' | ||
androidTestImplementation 'androidx.test:rules:1.3.0' | ||
androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.0.2' | ||
|
||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' | ||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_ktx_version" | ||
implementation "android.arch.lifecycle:extensions:1.1.1" | ||
implementation 'com.google.code.gson:gson:2.8.5' | ||
|
||
implementation "com.intuit.sdp:sdp-android:$sdp_version" | ||
implementation "com.intuit.ssp:ssp-android:$sdp_version" | ||
|
||
implementation "com.google.dagger:hilt-android:$hilt_android" | ||
implementation "androidx.hilt:hilt-lifecycle-viewmodel:$hilt_lifecycle" | ||
kapt "com.google.dagger:hilt-android-compiler:$hilt_android" | ||
kapt "androidx.hilt:hilt-compiler:$hilt_lifecycle" | ||
|
||
implementation "androidx.activity:activity-ktx:$activity_ktx_version" | ||
//Retrofit | ||
implementation 'com.squareup.retrofit2:retrofit:2.9.0' | ||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' | ||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" | ||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_ktx_version" | ||
|
||
implementation 'com.github.bumptech.glide:glide:4.12.0' | ||
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Add project specific ProGuard rules here. | ||
# You can control the set of applied configuration files using the | ||
# proguardFiles setting in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.suki.newsapp | ||
|
||
import androidx.test.platform.app.InstrumentationRegistry | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
|
||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
import org.junit.Assert.* | ||
|
||
/** | ||
* Instrumented test, which will execute on an Android device. | ||
* | ||
* See [testing documentation](http://d.android.com/tools/testing). | ||
*/ | ||
@RunWith(AndroidJUnit4::class) | ||
class ExampleInstrumentedTest { | ||
@Test | ||
fun useAppContext() { | ||
// Context of the app under test. | ||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext | ||
assertEquals("com.suki.newsapp", appContext.packageName) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="com.suki.newsapp"> | ||
|
||
<uses-permission android:name="android.permission.INTERNET" /> | ||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> | ||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | ||
|
||
<application | ||
android:name=".NewApplication" | ||
android:allowBackup="true" | ||
android:icon="@mipmap/ic_launcher" | ||
android:label="@string/app_name" | ||
android:roundIcon="@mipmap/ic_launcher_round" | ||
android:supportsRtl="true" | ||
android:theme="@style/Theme.NewsApp"> | ||
<activity android:name=".ui.details.NewsDetailsActivity"></activity> | ||
<activity android:name=".ui.list.MainActivity"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN" /> | ||
|
||
<category android:name="android.intent.category.LAUNCHER" /> | ||
</intent-filter> | ||
</activity> | ||
</application> | ||
|
||
</manifest> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.suki.newsapp | ||
|
||
import android.app.Application | ||
import dagger.hilt.android.HiltAndroidApp | ||
|
||
@HiltAndroidApp | ||
class NewApplication : Application(){ | ||
|
||
override fun onCreate() { | ||
super.onCreate() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package com.suki.newsapp.di | ||
|
||
import com.google.gson.Gson | ||
import com.google.gson.GsonBuilder | ||
import com.suki.newsapp.remote.NewsDataSource | ||
import com.suki.newsapp.remote.NewsService | ||
import com.suki.newsapp.repository.NewsRepository | ||
import com.suki.newsapp.util.Constants.Companion.BASE_URL | ||
import dagger.Module | ||
import dagger.Provides | ||
import dagger.hilt.InstallIn | ||
import dagger.hilt.android.components.ApplicationComponent | ||
import retrofit2.Retrofit | ||
import retrofit2.converter.gson.GsonConverterFactory | ||
import javax.inject.Singleton | ||
|
||
@Module | ||
@InstallIn(ApplicationComponent::class) | ||
object AppModule { | ||
|
||
@Singleton | ||
@Provides | ||
fun provideRetrofit(gson: Gson) : Retrofit = Retrofit.Builder() | ||
.baseUrl(BASE_URL) | ||
.addConverterFactory(GsonConverterFactory.create(gson)) | ||
.build() | ||
|
||
@Provides | ||
fun provideGson(): Gson = GsonBuilder().create() | ||
|
||
@Provides | ||
fun provideNewsService(retrofit: Retrofit): NewsService = retrofit.create(NewsService::class.java) | ||
|
||
@Provides | ||
fun provideRepository(newsDataSource: NewsDataSource): NewsRepository = NewsRepository(newsDataSource) | ||
|
||
@Provides | ||
fun provideNewsDataSource (newsService: NewsService): NewsDataSource = NewsDataSource(newsService) | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.suki.newsapp.entities | ||
|
||
import android.os.Parcelable | ||
import kotlinx.android.parcel.Parcelize | ||
|
||
@Parcelize | ||
data class Byline( | ||
val organization: String, | ||
val original: String, | ||
val person: List<Person> | ||
): Parcelable |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.suki.newsapp.entities | ||
|
||
import android.os.Parcel | ||
import android.os.Parcelable | ||
import android.widget.ImageView | ||
import androidx.annotation.IdRes | ||
import androidx.databinding.BindingAdapter | ||
import com.bumptech.glide.Glide | ||
import com.suki.newsapp.R | ||
import kotlinx.android.parcel.Parceler | ||
import kotlinx.android.parcel.Parcelize | ||
import kotlinx.android.synthetic.main.activity_main.view.* | ||
import kotlinx.android.synthetic.main.layout_grid_item.view.* | ||
import java.text.SimpleDateFormat | ||
|
||
|
||
@Parcelize | ||
data class Doc( | ||
val _id: String, | ||
val abstract: String, | ||
val document_type: String, | ||
val headline: Headline, | ||
val keywords: List<Keyword>, | ||
val lead_paragraph: String, | ||
val multimedia: List<Multimedia>, | ||
val news_desk: String, | ||
val print_page: String?, | ||
val print_section: String?, | ||
val pub_date: String, | ||
val section_name: String, | ||
val snippet: String, | ||
val source: String, | ||
val type_of_material: String, | ||
val uri: String, | ||
val web_url: String, | ||
val word_count: Int, | ||
var display_date: String | ||
): Parcelable | ||
|