SunFlower을 분석하면서 하나씩 따라해보는게 좋겠다 싶어서 테스트 프로젝트를 만들어본다.
doojuns-ordinary.tistory.com/42?category=994822
1. DI 종속성 주입 (sunflower 분석 ,hilt, dagger)
DI Dependency Injection 프로그래밍에 많이 사용되면 방법이며 안드로이드 개발에 적합하다고 함 다음과 같은 이점이 있다고 한다. 1) 코드 재사용 가능 2) 코드 리팩토리 편의성 3) 테스트 편의성
doojuns-ordinary.tistory.com
위의 목차에서 SunFlower를 분석하는중
더보기
화면에서 msg를 보내고 msg를 페이징해서 받아오도록 만드는게 우선 목표
패키지는 이렇게 생김.. 연습이라 대충만듦..
Room과 Paging을 사용하기 위해서 Gradle에 추가함
/*페이징*/
def paging_version = "3.0.0-beta02"
implementation "androidx.paging:paging-runtime:$paging_version"
implementation "androidx.paging:paging-compose:1.0.0-alpha08"
/*룸*/
def room_version = "2.3.0-alpha02"
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:$room_version"
/*힐트*/
implementation "com.google.dagger:hilt-android:2.35"
kapt "com.google.dagger:hilt-android-compiler:2.35"
kapt "androidx.lifecycle:lifecycle-compiler:2.4.0-alpha01"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
/*코루틴*/
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
implementation "androidx.fragment:fragment-ktx:1.3.0"
1. 힐트를 사용하기 위해서 어플리케이션 단에서 힐트를 추가함
@HiltAndroidApp
class MyApplication :Application() {
}
2. 메세지를 저장하기 위한 데이터베이스를 만들자
addCallBack을 사용할때 기존에는 ViewmodelScope를 사용해서 만들었었는데 SunFlower을 보니까 work를 사용하면서 더 편리하게 사용하더라. 근데 나는 아직 공부가 덜되서 대충 만들었음... work는 조만간에 공부해서 업데이트 해야겠다.
@Database(entities = [MsgData::class] , version = 1 , exportSchema = false)
abstract class MsgDatabase :RoomDatabase() {
abstract fun msgDao() :MsgDao
companion object{
@Volatile
private var INSTANCE:MsgDatabase? = null
fun getDatabase(
context: Context,
):MsgDatabase {
if(INSTANCE ==null){
val instance = Room.databaseBuilder(
context.applicationContext,
MsgDatabase::class.java,
"msg.db"
).build()
INSTANCE = instance
}
return INSTANCE!!
}
}
}
3.Dao, Entity를 만들기 그리고Module만들기
@Entity(tableName = "msg")
data class MsgData (
@PrimaryKey(autoGenerate = true) val id : Int =0,
@ColumnInfo(name = "chat") val msg : String
)
@Dao
interface MsgDao{
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertMsg(msgData : MsgData)
@Query("SELECT * FROM msg ORDER BY id")
fun getmsg(): PagingSource<Int,MsgData>
}
@InstallIn(SingletonComponent::class)
@Module
class MsgModule {
@Singleton
@Provides
fun provideMsgDatabase(@ApplicationContext context: Context):MsgDatabase{
return MsgDatabase.getDatabase(context)
}
@Provides
fun providDao(myApp :MsgDatabase):MsgDao{
return myApp.msgDao()
}
}
이 모듈을 안쓰면 오류가 생기니까 꼭 만들기 원래는 Dagger쓸 때는 더 복잡했다는데 안써봐서 편한건지 모르겟음.
확실히 힐트를 쓰면서 필요한 상용구가 많이 줄었다
4.Repository와 ViewModel
@Singleton
class MsgRepository @Inject constructor( private val msgDao: MsgDao) {
suspend fun sendMsg(msg:String){
val msg = MsgData(msg = msg)
msgDao.insertMsg(msg)
}
fun getPagedMsg(): Flow<PagingData<MsgData>> = Pager(
config = PagingConfig(enablePlaceholders = false,pageSize = 3)
){
msgDao.getmsg()
}.flow
}
@HiltViewModel
class MsgViewmodel @Inject constructor(private val repository: MsgRepository) : ViewModel(){
fun addMsg(msg:String){
viewModelScope.launch {
repository.sendMsg(msg)
}
}
fun getMsg(): kotlinx.coroutines.flow.Flow<PagingData<MsgData>> {
val flow = repository.getPagedMsg().cachedIn(viewModelScope)
return flow
}
}
5. Fragment에서 모든 작동을 하니까
@AndroidEntryPoint
class MsgFragment :Fragment(){
private val msgViewmodel : MsgViewmodel by viewModels()
private var searchJob: Job? = null
private val adapter = MsgAdapter()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val binding =DataBindingUtil.inflate<FragmentMsgBinding>(
inflater,
R.layout.fragment_msg,
container,
false
).apply {
viewModel = msgViewmodel
callback = Callback {
val text = input.text.toString()
msgViewmodel.addMsg(text)
input.text?.clear()
}
}
binding.chatRv.adapter = adapter
getMsg()
return binding.root
}
fun getMsg(){
searchJob?.cancel()
searchJob = lifecycleScope.launch {
msgViewmodel.getMsg().collectLatest {
adapter.submitData(it)
}
}
}
fun interface Callback {
fun add()
}
}
결론)
1. work 공부해야지
2. pagingSource가 변경되면서 페이징데이터도 초기화 되서 다시 로드하는데 이거 어떻게 고칠 수 있는 방법이 없을까?
3. 파이어베이스랑 연결해서 담번에 해봐야겠다
'안드로이드 jetpack > 적용해보기' 카테고리의 다른 글
2. workmanager 사용해보자 (0) | 2021.05.02 |
---|