ViewModelFactory 는 네트워크 통신을 하거나 Repository, Local DB(ROOM or SQLite)와 연결을 하는 등에 사용된다.

 

 

MainViewModel.kt

import android.util.Log
import androidx.lifecycle.ViewModel

class MainViewModel(num:Int) : ViewModel() {

    init{
       //데이터 결과를 로고로 찍으려함.
        Log.d("MainViewModel",num.toString())
    }

}
 

MainViewModelFactory.kt

class MainViewModelFactory(private val num : Int) : ViewModelProvider.Factory {

    override fun <T : ViewModel> create(modelClass: Class<T>): T {

        if(modelClass.isAssignableFrom(MainViewModel::class.java)){
            return MainViewModel(num) as T
        }
        throw IllegalArgumentException("Unknown ViewModel Class")

    }
}
 

처음 위 코드를 작성할때 Error가 났음.

gradle 파일에 아래의 코드를 추가하여 에러를 해결함.

 

build.gradle

 kotlinOptions {
        jvmTarget = '1.8'
        //아래코드를 넣어야 ViewModelFactory에 오류가 나지않음.
        freeCompilerArgs += [
                "-Xjvm-default=all",
        ]

    }
 

 

MainActivty.kt

//ViewModelFactory

class MainActivity : AppCompatActivity() {

    lateinit var viewModel : MainViewModel
    lateinit var viewModelFactory : MainViewModelFactory

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        viewModelFactory = MainViewModelFactory(5000)
        viewModel = ViewModelProvider(this,viewModelFactory).get(MainViewModel::class.java)


    }
}
 

실행 결과:

로고에 데이터가 찍힌 모습.

 

'Android > ViewModel' 카테고리의 다른 글

Activity/Fragment - ViewModel공유  (0) 2022.11.21
ViewModel  (0) 2022.11.21

 

Fragment에서 ViewModel을 Activity에서처럼 사용하려 했으나 그럴 수 없었다.

Fragment 는 Activity에 붙어있어 Activity의 생명주기의 영향을 받기 때문.

 

if(savedInstanceState == null){
            val transaction = manager.beginTransaction()
            val fragment = TestFragment()
            transaction.replace(R.id.frameArea,fragment)
            transaction.addToBackStack(null)
            transaction.commit()
        }
 

위 코드와 같이 예외처리로 Fragment 정보를 생명주기가 바뀜에 영향받지않게 할 수 있으나 비추천.

 

 

 

 

 

ViewModel은 Activity/Fragment간 데이터를 공유하거나, Activity 값을 Fragment에서 쓰고싶거나,

Fragment에서 값을 ViewModel의 값으로 사용할 때 쓴다.

 

 

먼저 아래의 코드를 gradle에 추가.(주석 아래 코드)

 

 

build.gradle

   implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

   //fragment activity viewModel 공유가능.
    implementation 'androidx.fragment:fragment-ktx:1.5.3'
}
 

 

MainActivity.kt

//ViewModel -> Activity/Framgent 공유
//why -> Activity의 값을 Fragment 쓰고 싶거나
// Fragment에서 값을 ViewModel의 값으로 사용하기 위해서.


class MainActivity : AppCompatActivity() {

    lateinit var binding : ActivityMainBinding
    lateinit var viewModel : MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)


        binding.resultArea.text = viewModel.getCount().toString()

        binding.plus.setOnClickListener {

            viewModel.plus()
            binding.resultArea.text = viewModel.getCount().toString()
        }

        binding.minus.setOnClickListener {

            viewModel.minus()
            binding.resultArea.text = viewModel.getCount().toString()


        }

        val manager = supportFragmentManager

        binding.showFragment.setOnClickListener {
            val transaction = manager.beginTransaction()
            val fragment = TestFragment()
            transaction.replace(R.id.frameArea,fragment)
            transaction.addToBackStack(null)
            transaction.commit()

        }



    }
}
 

 

 

 

MainViewModel.kt

class MainViewModel: ViewModel() {

    var countValue = 0

    fun plus(){
        countValue++
    }
    fun minus(){
        countValue--
    }

    fun getCount() : Int{

        return countValue

    }

}
 

TestFragment.kt

class TestFragment : Fragment() {

    private lateinit var binding : FragmentTestBinding
    private val viewModel : MainViewModel by activityViewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
      

        binding = DataBindingUtil.inflate(inflater,R.layout.fragment_test,container,false)

        binding.fragmentText.text = viewModel.getCount().toString()

        return binding.root
    }


}
 

 

 

Activity와 Fragment간 데이터가 공유된 화면.

 

'Android > ViewModel' 카테고리의 다른 글

ViewModelFactory  (0) 2022.11.21
ViewModel  (0) 2022.11.21

상태(LifeCycle:안드로이드 생명주기)가 변경될 때마다 데이터를 관리해야하는데 UI 컨트롤러(Activity, Fragment)에서 모든 것을 다 하려고 하면 복잡해진다. -> ViewModel 을 사용하면 테스트나 관리가 용이하다.

onSaveInstanceState()를 사용해서 데이터를 관리할 수도 있지만 적절하지 않다.

 

MainViewModel.kt

// ViewModel에서 저렇게 아래와 같이 따랑 변수하나만 만들어서
// 사용하지는 않고 LiveData(등등)을 이용해서 함께 씀.

//아래는 예제일뿐.

class MainViewModel : ViewModel() {

    var countValue = 0

    init {
        Log.d("MainViewModel", "init")
    }


    fun plus() {
        countValue++
        Log.d("MainViewModel", countValue.toString())

    }

    fun minus() {
        countValue--
        Log.d("MainViewModel", countValue.toString())

    }

    fun getCoutnValue(): Int {

        return countValue

    }


}
 

MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var viewModel : MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

        Log.d("MainActivity","onCreate")

        val plusBtn : Button = findViewById(R.id.plus)
        val minusBtn : Button = findViewById(R.id.minus)

        val resultArea: TextView = findViewById(R.id.result)

        resultArea.text = viewModel.countValue.toString()

        plusBtn.setOnClickListener {
            viewModel.plus()
            resultArea.text = viewModel.countValue.toString()

        }


        minusBtn.setOnClickListener {
            viewModel.minus()
            resultArea.text = viewModel.countValue.toString()

        }


    }

    
}
 

Activity의 주기가 다시 돌아도 데이터가 유지된다.

 

'Android > ViewModel' 카테고리의 다른 글

ViewModelFactory  (0) 2022.11.21
Activity/Fragment - ViewModel공유  (0) 2022.11.21

+ Recent posts