Android ViewModel အကြောင်း

ViewModel ဆိုတာဘာလဲ

Android ViewModel ဆိုတာက ပုံမှန် Model တစ်ခုလိုပါပဲ
အဓိက ကွဲသွားတာကတော့ Model ဆိုတာက Person တို့ Employee တို့လို Object တွေဖြစ်ပြီးတော့ ViewModel ကတော့ View အတွက်သီးသန့် Model ပဲဖြစ်ပါတယ်။
View ဆိုတာတော့ Android ရဲ့ Activity တို့ Fragment တို့အကုန်လုံးကို ခြုံပြောတာပါ။

ViewModel ကို ဘာကြောင့်သုံးရတာလဲ?

Android app တွေရေးတဲ့အခါမှာ developer တွေ ကြုံတွေ့ရလေ့ရှိတဲ့ ပြဿနာက View တွေ state ပြောင်းသွားရင် data ပျောက်သွားတတ်တဲ့ ပြဿနာပါ။ ဥပမာဆိုရင် ဖုန်းကို ထောင်လိုက် (Portrait) သုံးနေရာကနေ အလျားလိုက် (Landscape) လှည့်လိုက်တဲ့ အချိန်မှာ data ပျောက်သွားတတ်ပါတယ်။

ဒီလို ဘာကြောင့်ဖြစ်ရတာလဲဆိုတော့ View တွေက state ပြောင်းလဲသွားရင် UI ကို အစကနေ ပြန်ဆောက်တဲ့အတွက်ကြောင့်ပါ။
Data အသွင်းအထုတ်လုပ်တာတွေ ၊ တွက်ချက်တာတွေကို Activity / Fragment ထဲမှာ ရေးထားတဲ့အခါမှာ အခုလို state ပြောင်းလဲသွားတဲ့အခါမှာ အကုန်လုံးကို အသစ်ပြန်စတဲ့အတွက် တွက်ချက်ထားတဲ့ data တွေကလဲ အသစ်ပြန်ဖြစ်သွားပါတယ်။

အပေါ်ကပုံမှာ ပြထားတဲ့ Example မှာဆိုရင် Score ကို တွက်ချက်ပြီးတော့ ရလဒ်ကို Activity/Fragment ထဲမှာပဲ variable အနေနဲ့ သိမ်းထားပါတယ်။ အဲ့ဒီအချိန်မှာ ဖုန်းကို လှည့်လိုက်ရင် Activity/Fragment ထဲမှာ ရှိတဲ့ process အကုန်လုံးကို အစအဆုံး ပြန်ဆောက်တဲ့အတွက် တွက်ချက်ထားတဲ့ ရလဒ်က ပျောက်သွားတာပါ။

အဲ့လိုမျိုးမဖြစ်ရအောင် ViewModel ဆိုတာကို သုံးလို့ရပါတယ်။
သူရဲ့သဘောတရားကတော့ View ထဲမှာ ပြမယ့် data တွေ တွက်ချက်မှုတွေကို View ထဲမှာမရေးထားပဲ သီးသန့် ခွဲထုတ်လိုက်တာပါ။
အဲ့လို ခွဲထုတ်ထားတဲ့အတွက် View က state ပြောင်းလဲသွားလို့ အစကပြန်ဆောက်ရင် ViewModel က မပြောင်းလဲပဲ ကျန်ခဲ့ပါတယ်။ View က data ကို ပြန်ယူသုံးတဲ့အခါမှာ data က မပြောင်းလဲ မပျက်ဆီးပဲ ကျန်ခဲ့ပါတယ်။

ViewModel ကို ဘယ်လိုသုံးမလဲ

ViewModel စသုံးမယ်ဆို ရင် ပထမဆုံးလုပ်ရမှာကတော့ Activity/Fragment တစ်ခုချင်းဆီအတွက် ViewModel တစ်ခုဆီဆောက်ပေးဖို့ပါ။ တချို့သော အခြေအနေတွေမှာ ViewModel ကို ပြန်သုံးလို့ရပေမယ့် ဖြစ်နိုင်ရင်တော့ Activity/Fragment တစ်ခုခြင်းဆီအတွက် ViewModel တစ်ခုဆီ ဆောက်ထားသင့်ပါတယ်။

ပုံမှန် Android activity တစ်ခုဆောက်မယ်ဆိုရင် ဒီလိုပုံစံမျိုး ဖြစ်ရှိပါတယ်

// ExampleActivity.java
public class ExampleActivity extends AppCompatActivity {
    private int score = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.example);

        Button addBtn = (Button) findViewById(R.id.btn_add_point);
        TextView textScore = (TextView) findViewById(R.id.text_score);

        textScore.setText(String.valueOf(score));

        addBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                score = score + 1;
                textScore.setText(String.valueOf(score));
            }
        });
    }
}
<!-- activity_example.xml -->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".ExampleActivity"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">
    <TextView
        android:text="0"
        android:id="@+id/text_score"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/btn_add_point"
        android:layout_gravity="center"
        android:text="+1 Point"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

"+1 Point" ဆိုတဲ့ button ရှိပြီးတော့ နှိပ်လိုက်ရင် Activity ထဲမှာရှိတဲ့ score ဆိုတဲ့ variable ကို 1 ပေါင်းပေးတယ်။
ပြီးရင် text_score ဆိုတဲ့ TextView မှာ ရလဒ်ကို ပြပေးတယ်။

ဒီလို ပုံမှန် ရေးနေကျအတိုင်းရေးထားတဲ့အခါမှာ +1 ကို နှိပ်တိုင်း score ကို တိုးပေးပြီး ရလဒ်ကို ပြနေပေမယ့် ရုတ်တရက် ဖုန်းကို လှည့်လိုက်တဲ့အခါမှာ score က 0 ပြန်ဖြစ်သွားပါလိမ့်မယ်။
ဘာကြောင့်လဲဆိုတော့ View state ပြောင်းလဲသွားတဲ့အချိန်မှာ onCreate method ကို အစအဆုံး ပြန်ပြီး process လုပ်လိုက်လို့ပါ။

အဲ့လိုမဖြစ်ရအောင် ကျွန်တော်တို့ ViewModel ကို စသုံးပါမယ်။
ပထမဆုံး ကျွန်တော်တို့ ExampleActivity အတွက် ViewModel ဖြစ်တဲ့ ExampleViewModel ကိုအရင်စရေးပါမယ်။

//ExampleViewModel
public class ExampleViewModel extends ViewModel {
    public int score = 0;
}

score ကို ExampleActivity ထဲမှာ မထားတော့ပဲ ExampleViewModel ထဲမှာ ခွဲရေးလိုက်ပါတယ်။
ပြီးရင် ExampleActivity ကို ဒီလိုမျိုးပြန်ပြင်လိုက်ပါတယ်။

public class ExampleActivity extends AppCompatActivity {
    private ExampleViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.example);

        // ဒီ Activity အတွက် ViewModel က ExampleViewModel ဖြစ်ပါတယ်ဆိုတာကို ဒီနေရာမှာ define လုပ်ပေးရပါတယ်
        viewModel = ViewModelProviders.of(this).get(ExampleViewModel.class);

        Button addBtn = (Button) findViewById(R.id.btn_add_point);
        TextView textScore = (TextView) findViewById(R.id.text_score);

        // score ကို activity ထဲမှာမထားတော့ပဲ အကုန်လုံး ExampleViewModel ထဲကပဲ ခေါ်သုံးပါတော့တယ်
        textScore.setText(String.valueOf(viewModel.score));

        addBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewModel.score = viewModel.score +1;
                textScore.setText(String.valueOf(viewModel.score));
            }
        });
    }
}

Code ကို အခုလိုပြင်ပြီးသွားပြီ ဆိုရင်တော့ score ဘယ်လိုပဲပေါင်းပေါင်း ဖုန်းကို ဘယ်လောက်ပဲလှည့်လှည့် score က တွက်လက်စအတိုင်း ကျန်ရှိနေမှာဖြစ်ပါတယ်။
ViewModel သုံးတဲ့အခါမှာ သတိထားရမှာကတော့ ViewModel က Activity ရဲ့ context ကို access လုပ်ခွင့်မရှိပါဘူး။
context မဖြစ်မနေသုံးရမယ့် အနေအထားဖြစ်နေရင်တော့ ViewModel ကို extend လုပ်မယ့်အစား AndroidViewModel ဆိုတာကို extend လုပ်ပြီးတော့ applicationContext ကို သုံးနိုင်ပါတယ်။

Comments

  • Installation

    ViewModel ကိုသုံးဖို့အတွက် app ရဲ့ gradle dependencies မှာ ဒီ library ကိုထည့်ပေးရပါမယ်။

    dependencies{
         implementation "android.arch.lifecycle:extensions:1.1.1"
    }
    
Sign In or Register to comment.