Skip to content

Commit e7aff81

Browse files
Add News app code
- Add retrofit, coil, viewmodel dependencies - Add news related code
1 parent 5bb74fc commit e7aff81

File tree

11 files changed

+247
-12
lines changed

11 files changed

+247
-12
lines changed

app/build.gradle

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ android {
3737
compose true
3838
}
3939
composeOptions {
40+
4041
kotlinCompilerExtensionVersion '1.1.1'
4142
}
4243
packagingOptions {
@@ -53,11 +54,20 @@ dependencies {
5354
implementation 'androidx.activity:activity-compose:1.6.1'
5455
implementation "androidx.compose.ui:ui:$compose_version"
5556
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
56-
implementation 'androidx.compose.material3:material3:1.1.0-alpha03'
57+
implementation 'androidx.compose.material3:material3:1.0.1'
58+
59+
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
60+
//retrofit
61+
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
62+
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
63+
//coil
64+
implementation("io.coil-kt:coil-compose:2.2.2")
65+
5766
testImplementation 'junit:junit:4.13.2'
5867
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
5968
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
6069
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
6170
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
6271
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
72+
6373
}

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools">
44

5+
<uses-permission android:name="android.permission.INTERNET" />
56
<application
67
android:allowBackup="true"
78
android:dataExtractionRules="@xml/data_extraction_rules"

app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/MainActivity.kt

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,28 @@ package com.lahsuak.apps.jetpackcomposebasic
33
import android.os.Bundle
44
import androidx.activity.ComponentActivity
55
import androidx.activity.compose.setContent
6+
import androidx.compose.foundation.layout.Column
67
import androidx.compose.foundation.layout.fillMaxSize
8+
import androidx.compose.foundation.layout.fillMaxWidth
9+
import androidx.compose.foundation.layout.padding
10+
import androidx.compose.foundation.lazy.LazyColumn
11+
import androidx.compose.foundation.lazy.items
712
import androidx.compose.material3.MaterialTheme
813
import androidx.compose.material3.Surface
914
import androidx.compose.material3.Text
1015
import androidx.compose.runtime.Composable
16+
import androidx.compose.runtime.collectAsState
17+
import androidx.compose.runtime.getValue
1118
import androidx.compose.ui.Modifier
1219
import androidx.compose.ui.tooling.preview.Preview
20+
import androidx.compose.ui.unit.dp
21+
import androidx.lifecycle.ViewModel
22+
import androidx.lifecycle.viewmodel.compose.viewModel
23+
import com.lahsuak.apps.jetpackcomposebasic.model.News
24+
import com.lahsuak.apps.jetpackcomposebasic.ui.NewsItem
25+
import com.lahsuak.apps.jetpackcomposebasic.ui.elements.*
1326
import com.lahsuak.apps.jetpackcomposebasic.ui.theme.JetPackComposeBasicTheme
27+
import com.lahsuak.apps.jetpackcomposebasic.ui.viewmodel.NewsViewModel
1428

1529
class MainActivity : ComponentActivity() {
1630
override fun onCreate(savedInstanceState: Bundle?) {
@@ -22,20 +36,53 @@ class MainActivity : ComponentActivity() {
2236
modifier = Modifier.fillMaxSize(),
2337
color = MaterialTheme.colorScheme.background
2438
) {
25-
Greeting("Android")
39+
val newsViewModel: NewsViewModel = viewModel()
40+
newsViewModel.getNews("general")
41+
getNewsData(modifier = Modifier.fillMaxSize(), newsViewModel)
42+
// Column(Modifier.padding(vertical = 16.dp, horizontal = 8.dp)) {
43+
// RadioButtonUI()
44+
// CheckBoxUI("Accept term and condition")
45+
// EditTextUI("Enter your name", modifier = Modifier.fillMaxWidth())
46+
// PasswordFieldUI("Enter your password", modifier = Modifier.fillMaxWidth())
47+
// Search(placeHolderMsg = "Search", modifier = Modifier.fillMaxWidth())
48+
// SnackBarUI("Hello it's me snackbar")
49+
// }
2650
}
2751
}
2852
}
2953
}
3054
}
31-
/***
32-
Composable functions :
33-
A composable function is a regular function annotated with @Composable.
34-
This enables your function to call other @Composable functions within it.
35-
You can see how the Greeting function is marked as @Composable.
36-
This function will produce a piece of UI hierarchy displaying the given input,
37-
String. Text is a composable function provided by the library.
38-
***/
55+
56+
@Composable
57+
fun getList(): List<News> {
58+
val list = mutableListOf<News>()
59+
for (i in 0..10) {
60+
list.add(
61+
News(
62+
"Kaushal",
63+
"Ness",
64+
"https://pixabay.com/get/gc5bde75f8a92a997aa842681d52d37e41990f5e639497bad55c1cf9921835528340e1269788a027624b201d17734fb431c5269478e54aece4e65f7581452fe98_640.jpg",
65+
"https://pixabay.com/get/gc5bde75f8a92a997aa842681d52d37e41990f5e639497bad55c1cf9921835528340e1269788a027624b201d17734fb431c5269478e54aece4e65f7581452fe98_640.jpg",
66+
)
67+
)
68+
}
69+
return list
70+
}
71+
72+
@Composable
73+
fun getNewsData(
74+
modifier: Modifier,
75+
newsViewModel: NewsViewModel
76+
) {
77+
val newsList by newsViewModel.newsFlow.collectAsState()
78+
// val d = getList()
79+
LazyColumn(modifier = modifier.padding(vertical = 4.dp)) {
80+
items(items = newsList) { news ->
81+
NewsItem(news = news)
82+
}
83+
}
84+
}
85+
3986
@Composable
4087
fun Greeting(name: String) {
4188
Text(text = "Hello $name!")
@@ -45,6 +92,14 @@ fun Greeting(name: String) {
4592
@Composable
4693
fun DefaultPreview() {
4794
JetPackComposeBasicTheme {
48-
Greeting("Android")
95+
Surface(
96+
modifier = Modifier.fillMaxSize(),
97+
color = MaterialTheme.colorScheme.background
98+
) {
99+
RadioButtonUI()
100+
CheckBoxUI("Accept term and condition")
101+
EditTextUI("Enter your name", modifier = Modifier.fillMaxWidth())
102+
PasswordFieldUI("Enter your password", modifier = Modifier.fillMaxWidth())
103+
}
49104
}
50105
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.lahsuak.apps.jetpackcomposebasic.api
2+
3+
import retrofit2.Retrofit
4+
import retrofit2.converter.gson.GsonConverterFactory
5+
6+
object ApiClient {
7+
val apiInterface: NewApi by lazy {
8+
Retrofit.Builder()
9+
.baseUrl(NewApi.BASE_URL)
10+
.addConverterFactory(
11+
GsonConverterFactory.create()
12+
)
13+
.build()
14+
.create(NewApi::class.java)
15+
}
16+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.lahsuak.apps.jetpackcomposebasic.api
2+
3+
import com.lahsuak.apps.jetpackcomposebasic.model.News
4+
import com.lahsuak.apps.jetpackcomposebasic.model.NewsParentModel
5+
import retrofit2.http.GET
6+
import retrofit2.http.Path
7+
import retrofit2.http.Query
8+
9+
10+
interface NewApi {
11+
companion object {
12+
const val BASE_URL = "https://saurav.tech"//NewsAPI/top-headlines/category/general/in.json"
13+
}
14+
15+
@GET("/NewsAPI/top-headlines/category/general/in.json")
16+
suspend fun getNews(
17+
// @Path("category")
18+
// category: String
19+
): NewsParentModel
20+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.lahsuak.apps.jetpackcomposebasic.model
2+
3+
data class News (
4+
val description:String,
5+
val title:String,
6+
val url:String,
7+
val urlToImage:String,
8+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.lahsuak.apps.jetpackcomposebasic.model
2+
3+
data class NewsParentModel(
4+
val status: String,
5+
val totalResults: Int,
6+
val articles: List<News>
7+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.lahsuak.apps.jetpackcomposebasic.repo
2+
3+
import com.lahsuak.apps.jetpackcomposebasic.api.ApiClient
4+
import com.lahsuak.apps.jetpackcomposebasic.api.NewApi
5+
import com.lahsuak.apps.jetpackcomposebasic.model.News
6+
import com.lahsuak.apps.jetpackcomposebasic.model.NewsParentModel
7+
8+
class NewsRepository(private val apiInterface: NewApi= ApiClient.apiInterface) {
9+
suspend fun getNews(category: String): NewsParentModel {
10+
return apiInterface.getNews(
11+
// category
12+
)
13+
}
14+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.lahsuak.apps.jetpackcomposebasic.ui
2+
3+
import androidx.compose.foundation.Image
4+
import androidx.compose.foundation.layout.*
5+
import androidx.compose.material3.MaterialTheme
6+
import androidx.compose.material3.Surface
7+
import androidx.compose.material3.Text
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.ui.Modifier
10+
import androidx.compose.ui.graphics.Color
11+
import androidx.compose.ui.layout.ContentScale
12+
import androidx.compose.ui.platform.LocalContext
13+
import androidx.compose.ui.text.style.TextOverflow
14+
import androidx.compose.ui.tooling.preview.Preview
15+
import androidx.compose.ui.unit.dp
16+
import coil.compose.rememberAsyncImagePainter
17+
import coil.request.ImageRequest
18+
import com.lahsuak.apps.jetpackcomposebasic.R
19+
import com.lahsuak.apps.jetpackcomposebasic.model.News
20+
import com.lahsuak.apps.jetpackcomposebasic.ui.theme.JetPackComposeBasicTheme
21+
22+
@Composable
23+
fun NewsItem(news: News) {
24+
val painter = rememberAsyncImagePainter(
25+
model = ImageRequest.Builder(LocalContext.current)
26+
.data(news.urlToImage)
27+
.placeholder(R.drawable.ic_launcher_foreground)
28+
.crossfade(true)
29+
.build(),
30+
contentScale = ContentScale.FillWidth
31+
)
32+
Column(modifier = Modifier.fillMaxWidth()) {
33+
Image(
34+
painter = painter,
35+
contentDescription = null,
36+
modifier = Modifier
37+
.fillMaxWidth()
38+
.height(200.dp),
39+
)
40+
Text(
41+
text = news.title,
42+
style = MaterialTheme.typography.bodyMedium,
43+
maxLines = 1,
44+
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
45+
)
46+
Text(
47+
text = news.description,
48+
style = MaterialTheme.typography.bodySmall,
49+
maxLines = 3,
50+
overflow = TextOverflow.Ellipsis,
51+
color = Color.Gray,
52+
modifier = Modifier.padding(horizontal = 8.dp)
53+
)
54+
}
55+
}
56+
57+
58+
@Preview
59+
@Composable
60+
fun NewsItemPreview() {
61+
JetPackComposeBasicTheme {
62+
// A surface container using the 'background' color from the theme
63+
Surface(
64+
modifier = Modifier.fillMaxSize(),
65+
color = MaterialTheme.colorScheme.background
66+
) {
67+
NewsItem(
68+
news = News(
69+
"Kaushal",
70+
"Ness",
71+
"https://pixabay.com/get/gc5bde75f8a92a997aa842681d52d37e41990f5e639497bad55c1cf9921835528340e1269788a027624b201d17734fb431c5269478e54aece4e65f7581452fe98_640.jpg",
72+
"https://pixabay.com/get/gc5bde75f8a92a997aa842681d52d37e41990f5e639497bad55c1cf9921835528340e1269788a027624b201d17734fb431c5269478e54aece4e65f7581452fe98_640.jpg",
73+
)
74+
)
75+
}
76+
}
77+
}

app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/ui/theme/Color.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ val Pink80 = Color(0xFFEFB8C8)
88

99
val Purple40 = Color(0xFF6650a4)
1010
val PurpleGrey40 = Color(0xFF625b71)
11-
val Pink40 = Color(0xFF7D5260)
11+
val Pink40 = Color(0xFF7D5260)
12+
val Grey = Color(0xFF534F50)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.lahsuak.apps.jetpackcomposebasic.ui.viewmodel
2+
3+
import androidx.lifecycle.ViewModel
4+
import androidx.lifecycle.viewModelScope
5+
import com.lahsuak.apps.jetpackcomposebasic.model.News
6+
import com.lahsuak.apps.jetpackcomposebasic.repo.NewsRepository
7+
import kotlinx.coroutines.flow.MutableStateFlow
8+
import kotlinx.coroutines.flow.StateFlow
9+
import kotlinx.coroutines.launch
10+
11+
class NewsViewModel : ViewModel() {
12+
private val _newsFlow: MutableStateFlow<List<News>> = MutableStateFlow(emptyList())
13+
val newsFlow: StateFlow<List<News>>
14+
get() = _newsFlow
15+
16+
private val newsRepo: NewsRepository by lazy {
17+
NewsRepository()
18+
}
19+
20+
fun getNews(category: String) {
21+
viewModelScope.launch {
22+
val newsParentModel = newsRepo.getNews(category)
23+
_newsFlow.value = newsParentModel.articles
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)