5 лаба готова и сдана
This commit is contained in:
parent
ca101dfb80
commit
8e644e6ba0
@ -14,7 +14,8 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.MobileApp"
|
||||
tools:targetApi="31">
|
||||
tools:targetApi="31"
|
||||
android:networkSecurityConfig="@xml/network_security_config">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
|
@ -35,6 +35,7 @@ class MobileAppDataContainer(private val context: Context): MobileAppContainer {
|
||||
//OfflineStoryRepository(MobileAppDataBase.getInstance(context).storyDao())
|
||||
RestStoryRepository(ServerService.getInstance(),
|
||||
storyReposLocal,
|
||||
userReposLocal,
|
||||
MobileAppDataBase.getInstance(context),
|
||||
remoteKeyRepository)
|
||||
}
|
||||
@ -51,4 +52,8 @@ class MobileAppDataContainer(private val context: Context): MobileAppContainer {
|
||||
private val storyReposLocal: OfflineStoryRepository by lazy {
|
||||
OfflineStoryRepository(MobileAppDataBase.getInstance(context).storyDao())
|
||||
}
|
||||
|
||||
private val userReposLocal: OfflineUserRepository by lazy {
|
||||
OfflineUserRepository(MobileAppDataBase.getInstance(context).userDao())
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ import retrofit2.http.Query
|
||||
|
||||
interface ServerService {
|
||||
//USER
|
||||
@GET("USER/get/{id}")
|
||||
@GET("user/get/{id}")
|
||||
suspend fun getUser(
|
||||
@Path("id") id: Int,
|
||||
): UserRemote
|
||||
@ -39,6 +39,9 @@ interface ServerService {
|
||||
@Body user: UserRemote
|
||||
): UserRemote
|
||||
|
||||
@GET("user/getAll")
|
||||
suspend fun getUsers(): List<UserRemote>
|
||||
|
||||
//STORY
|
||||
@GET("story/get/{id}")
|
||||
suspend fun getStory(
|
||||
|
@ -6,11 +6,13 @@ import androidx.paging.PagingState
|
||||
import androidx.paging.RemoteMediator
|
||||
import androidx.room.withTransaction
|
||||
import com.example.mobileapp.api.model.toStory
|
||||
import com.example.mobileapp.api.model.toUser
|
||||
import com.example.mobileapp.database.MobileAppDataBase
|
||||
import com.example.mobileapp.database.entities.RemoteKeyType
|
||||
import com.example.mobileapp.database.entities.RemoteKeys
|
||||
import com.example.mobileapp.database.entities.Story
|
||||
import com.example.mobileapp.database.repositories.OfflineStoryRepository
|
||||
import com.example.mobileapp.database.repositories.OfflineUserRepository
|
||||
import com.example.mobileapp.database.repositories.RemoteKeysRepositoryImpl
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
@ -18,6 +20,7 @@ import java.io.IOException
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
class ServiceRemoteMediator(private val service: ServerService,
|
||||
private val storyRepository: OfflineStoryRepository,
|
||||
private val userRepository: OfflineUserRepository,
|
||||
private val database: MobileAppDataBase,
|
||||
private val dbRemoteKeyRepository: RemoteKeysRepositoryImpl
|
||||
) : RemoteMediator<Int, Story>() {
|
||||
@ -48,12 +51,14 @@ class ServiceRemoteMediator(private val service: ServerService,
|
||||
}
|
||||
|
||||
try {
|
||||
val users = service.getUsers().map { it.toUser() }
|
||||
val stories = service.getStories(page, state.config.pageSize).map { it.toStory() }
|
||||
val endOfPaginationReached = stories.isEmpty()
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.STORY)
|
||||
storyRepository.clearStories()
|
||||
userRepository.clearUsers()
|
||||
}
|
||||
val prevKey = if (page == 1) null else page - 1
|
||||
val nextKey = if (endOfPaginationReached) null else page + 1
|
||||
@ -66,6 +71,7 @@ class ServiceRemoteMediator(private val service: ServerService,
|
||||
)
|
||||
}
|
||||
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||
userRepository.insertUsers(users)
|
||||
storyRepository.insertStories(stories)
|
||||
}
|
||||
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
|
||||
|
@ -0,0 +1,64 @@
|
||||
package com.example.mobileapp.api.repository
|
||||
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.example.mobileapp.MobileAppContainer
|
||||
import com.example.mobileapp.api.ServerService
|
||||
import com.example.mobileapp.api.model.toMail
|
||||
import com.example.mobileapp.api.model.toMailRemote
|
||||
import com.example.mobileapp.database.entities.Mail
|
||||
import com.example.mobileapp.database.repositories.MailRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class RestMailRepository(private var service: ServerService): MailRepository {
|
||||
override fun getAllMails(): Flow<PagingData<Mail>> {
|
||||
return Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = MobileAppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = { MailPagingSource(service) }
|
||||
).flow
|
||||
}
|
||||
|
||||
override suspend fun getMail(id: Int): Mail? = service.getMail(id).toMail()
|
||||
|
||||
override suspend fun insertMail(mail: Mail) {
|
||||
service.createMail(mail.toMailRemote())
|
||||
}
|
||||
|
||||
override suspend fun updateMail(mail: Mail) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun deleteMail(mail: Mail) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
class MailPagingSource(private val service: ServerService) : PagingSource<Int, Mail>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Mail> {
|
||||
try {
|
||||
val nextPageNumber = params.key ?: 1
|
||||
val pageSize = params.loadSize
|
||||
|
||||
val response = service.getMails(nextPageNumber, pageSize)
|
||||
val mails = response.map { it.toMail() } // Преобразование MailRemote в Mail
|
||||
|
||||
return LoadResult.Page(
|
||||
data = mails,
|
||||
prevKey = if (nextPageNumber == 1) null else nextPageNumber - 1,
|
||||
nextKey = if (mails.isEmpty()) null else nextPageNumber + 1
|
||||
)
|
||||
} catch (exception: Exception) {
|
||||
return LoadResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, Mail>): Int? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package com.example.mobileapp.api.repository
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.example.mobileapp.MobileAppContainer
|
||||
import com.example.mobileapp.api.ServerService
|
||||
import com.example.mobileapp.api.ServiceRemoteMediator
|
||||
import com.example.mobileapp.api.model.toMail
|
||||
import com.example.mobileapp.api.model.toStory
|
||||
import com.example.mobileapp.api.model.toStoryRemote
|
||||
import com.example.mobileapp.database.MobileAppDataBase
|
||||
import com.example.mobileapp.database.entities.Mail
|
||||
import com.example.mobileapp.database.entities.Story
|
||||
import com.example.mobileapp.database.repositories.OfflineStoryRepository
|
||||
import com.example.mobileapp.database.repositories.OfflineUserRepository
|
||||
import com.example.mobileapp.database.repositories.RemoteKeysRepositoryImpl
|
||||
import com.example.mobileapp.database.repositories.StoryRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
class RestStoryRepository(private var service: ServerService,
|
||||
private val dbStoryRepository: OfflineStoryRepository,
|
||||
private val dbUserRepository: OfflineUserRepository,
|
||||
private val database: MobileAppDataBase,
|
||||
private val dbRemoteKeyRepository: RemoteKeysRepositoryImpl
|
||||
): StoryRepository {
|
||||
|
||||
override fun getAllStories(): Flow<PagingData<Story>> {
|
||||
val pagingSourceFactory = {
|
||||
dbStoryRepository.getAllStoriesPagingSource()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
return Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = MobileAppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
remoteMediator = ServiceRemoteMediator(
|
||||
service,
|
||||
dbStoryRepository,
|
||||
dbUserRepository,
|
||||
database,
|
||||
dbRemoteKeyRepository,
|
||||
),
|
||||
pagingSourceFactory = pagingSourceFactory
|
||||
).flow
|
||||
/*return Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = MobileAppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = { StoryPagingSource(service) }
|
||||
).flow*/
|
||||
}
|
||||
|
||||
override fun getStoriesByUserId(userId: Int): Flow<PagingData<Story>> {
|
||||
return Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = MobileAppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = { StoryPagingSource(service, userId) }
|
||||
).flow
|
||||
}
|
||||
|
||||
override suspend fun getStoryById(id: Int): Story? = service.getStory(id).toStory()
|
||||
|
||||
override suspend fun insertStory(story: Story) {
|
||||
service.createStory(story.toStoryRemote())
|
||||
}
|
||||
|
||||
override suspend fun updateStory(story: Story) {
|
||||
story.id?.let {
|
||||
service.updateStory(it, story.toStoryRemote())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun deleteStory(story: Story) {
|
||||
try {
|
||||
story.id?.let { this.service.deleteStory(it) }
|
||||
dbStoryRepository.deleteStory(story)
|
||||
}catch (ex: Exception){}
|
||||
}
|
||||
}
|
||||
|
||||
class StoryPagingSource(private val service: ServerService,
|
||||
private val userId: Int? = null) : PagingSource<Int, Story>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Story> {
|
||||
try {
|
||||
val nextPageNumber = params.key ?: 1
|
||||
val pageSize = params.loadSize
|
||||
|
||||
val response = if (userId != null) {
|
||||
service.getUserStories(nextPageNumber, pageSize, userId)
|
||||
} else {
|
||||
service.getStories(nextPageNumber, pageSize)
|
||||
}
|
||||
val stories = response.map { it.toStory() }
|
||||
|
||||
return LoadResult.Page(
|
||||
data = stories,
|
||||
prevKey = if (nextPageNumber == 1) null else nextPageNumber - 1,
|
||||
nextKey = if (stories.isEmpty()) null else nextPageNumber + 1
|
||||
)
|
||||
} catch (exception: Exception) {
|
||||
return LoadResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, Story>): Int? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
@ -208,9 +208,9 @@ fun MailListItem(item: Mail, navController: NavHostController,
|
||||
}
|
||||
|
||||
val userPhoto = remember { mutableStateOf<Bitmap>(BitmapFactory.decodeResource(context.resources, R.drawable.post)) }
|
||||
val userName = remember { mutableStateOf("") }
|
||||
val userName = remember { mutableStateOf("UserName") }
|
||||
|
||||
/*LaunchedEffect(Unit){
|
||||
LaunchedEffect(Unit){
|
||||
val user = userViewModel.getUser(item.userId)
|
||||
if (user != null) {
|
||||
userName.value = user.email
|
||||
@ -218,7 +218,7 @@ fun MailListItem(item: Mail, navController: NavHostController,
|
||||
userPhoto.value = user.photo
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
Card(
|
||||
modifier = Modifier
|
||||
|
@ -17,7 +17,7 @@ interface MailDao {
|
||||
fun getAll(): PagingSource<Int, Mail>
|
||||
|
||||
@Query("select * from mails where mails.id = :id")
|
||||
fun getById(id: Int): Flow<Mail?>
|
||||
suspend fun getById(id: Int): Mail?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insert(mail: Mail)
|
||||
|
@ -21,11 +21,14 @@ interface UserDao {
|
||||
suspend fun getByLogin(login: String): User?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insert(user: User)
|
||||
suspend fun insert(vararg user: User)
|
||||
|
||||
@Update
|
||||
suspend fun update(user: User)
|
||||
|
||||
@Delete
|
||||
suspend fun delete(user: User)
|
||||
|
||||
@Query("delete from stories")
|
||||
suspend fun deleteAll()
|
||||
}
|
@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
interface MailRepository {
|
||||
fun getAllMails(): Flow<PagingData<Mail>>
|
||||
|
||||
fun getMail(id: Int): Flow<Mail?>
|
||||
suspend fun getMail(id: Int): Mail?
|
||||
|
||||
suspend fun insertMail(mail: Mail)
|
||||
|
||||
|
@ -23,7 +23,7 @@ class OfflineMailRepository(private val mailDao: MailDao): MailRepository {
|
||||
).flow
|
||||
}
|
||||
|
||||
override fun getMail(id: Int): Flow<Mail?> = mailDao.getById(id)
|
||||
override suspend fun getMail(id: Int): Mail? = mailDao.getById(id)
|
||||
|
||||
override suspend fun insertMail(mail: Mail) = mailDao.insert(mail)
|
||||
|
||||
|
@ -2,6 +2,7 @@ package com.example.mobileapp.database.repositories
|
||||
|
||||
import com.example.mobileapp.api.model.UserRemoteSignIn
|
||||
import com.example.mobileapp.database.dao.UserDao
|
||||
import com.example.mobileapp.database.entities.Story
|
||||
import com.example.mobileapp.database.entities.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@ -17,4 +18,8 @@ class OfflineUserRepository(private val userDao: UserDao): UserRepository {
|
||||
override suspend fun updateUser(user: User) = userDao.update(user)
|
||||
|
||||
override suspend fun deleteUser(user: User) = userDao.delete(user)
|
||||
|
||||
suspend fun clearUsers() = userDao.deleteAll()
|
||||
suspend fun insertUsers(users: List<User>) =
|
||||
userDao.insert(*users.toTypedArray())
|
||||
}
|
@ -12,7 +12,7 @@ import kotlinx.coroutines.launch
|
||||
class MailViewModel(private val mailRepository: MailRepository): ViewModel() {
|
||||
val getAllMails: Flow<PagingData<Mail>> = mailRepository.getAllMails().cachedIn(viewModelScope)
|
||||
|
||||
fun getMail(id: Int): Flow<Mail?> = mailRepository.getMail(id)
|
||||
suspend fun getMail(id: Int): Mail? = mailRepository.getMail(id)
|
||||
|
||||
fun insertMail(mail: Mail) = viewModelScope.launch {
|
||||
mailRepository.insertMail(mail)
|
||||
|
@ -84,17 +84,6 @@ fun EditStoryScreen(navController: NavHostController, storyId: Int? = null,
|
||||
title.value = story.title
|
||||
description.value = story.description
|
||||
}
|
||||
/*storyViewModel.getStoryById(storyId).collect {
|
||||
if (it != null) {
|
||||
cover.value = it.cover
|
||||
}
|
||||
if (it != null) {
|
||||
title.value = it.title
|
||||
}
|
||||
if (it != null) {
|
||||
description.value = it.description
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,5 @@ fun ListMailScreen(navController: NavHostController,
|
||||
}
|
||||
}
|
||||
}
|
||||
//DataListScroll(navController, mails)
|
||||
}
|
||||
}
|
@ -36,33 +36,12 @@ fun ListStoryScreen(navController: NavHostController,
|
||||
factory = MobileAppViewModelProvider.Factory
|
||||
)) {
|
||||
val stories = storyViewModel.getStoriesByUserId.collectAsLazyPagingItems()
|
||||
/*val stories = remember { mutableStateListOf<Story>() }
|
||||
LaunchedEffect(Unit){
|
||||
withContext(Dispatchers.IO) {
|
||||
storyViewModel.getStoriesByUserId(GlobalUser.getInstance().getUser()?.id!!).collect {
|
||||
stories.clear()
|
||||
stories.addAll(it)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(BackgroundItem1)
|
||||
) {
|
||||
/*LazyColumn(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
){
|
||||
item {
|
||||
addNewListItem(navController, "editstory")
|
||||
}
|
||||
itemsIndexed(stories){ _, item ->
|
||||
StoryListItem(item = item, navController = navController)
|
||||
}
|
||||
}*/
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(1)
|
||||
) {
|
||||
|
@ -124,18 +124,17 @@ fun MailViewScreen(navController: NavHostController, mailId: Int,
|
||||
val postdate = remember { mutableStateOf<Long>(0) }
|
||||
|
||||
LaunchedEffect(Unit){
|
||||
mailViewModel.getMail(mailId).collect{
|
||||
if (it != null) {
|
||||
message.value = it.message
|
||||
postdate.value = it.postdate!!
|
||||
val user = userViewModel.getUser(it.userId)
|
||||
if (user != null) {
|
||||
if(user.photo != null) {
|
||||
photo.value = user.photo
|
||||
}
|
||||
userName.value = user.email
|
||||
}
|
||||
val mail = mailViewModel.getMail(mailId)
|
||||
if (mail != null) {
|
||||
message.value = mail.message
|
||||
postdate.value = mail.postdate!!
|
||||
}
|
||||
val user = mail?.let { userViewModel.getUser(it.userId) }
|
||||
if (user != null) {
|
||||
if(user.photo != null) {
|
||||
photo.value = user.photo
|
||||
}
|
||||
userName.value = user.email
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user