Nim : 09031981317002
Teknologi bergerak
Tugas Android 2
Model MVC (Model,view,controller)
Android Architecture: Message-based MVC
Model View Controller (MVC) adalah sebuah pola yang dapat membangun
proyek perangkat lunak lebih efektif karena dilakukan dengan memilih
komponen antara Model, View, dan Controller pada bagian - bagian dalam
proyek.
Part 1: Model
Dalam aplikasi ini pertama, ada kelas terpisah yang berisi model "data", dengan kata lain, apa pun yang mungkin berubah di lapisan Model selama siklus hidup aplikasi:@Immutable public final class ModelData implements Serializable { private static final long serialVersionUID = 1L; private final int answer; public ModelData(int answer) { this.answer = answer; } public final int getAnswer() { return answer; } }
Seperti yang Anda lihat, saya ingin menempatkan sebuah penjelasan deskriptif seperti Immutable sehingga saya ingat kelas ini sebenarnya berubah yang memberikan banyak manfaat seperti kemampuan untuk berbagi kasus antara benang dan lain-lain. Selain itu, saya membuat kelas Serializable - serialisasi itu akan memungkinkan untuk, misalnya, menerapkan "Save / Load" fitur.
Sedangkan untuk kelas Model itu sendiri adalah:
@ThreadSafe public class Model { public interface Listener { void onModelStateUpdated(Model model); } private ModelData data = new ModelData(0); private final Listlisteners = new ArrayList (); public Model() { } public final ModelData getData() { synchronized (this) { return data; } } public final void updateData() { // takes a while! SystemClock.sleep(5000); ModelData newData = new ModelData(new Random().nextInt(10) + 1); synchronized (this) { data = newData; } synchronized (listeners) { for (Listener listener : listeners) { listener.onModelStateUpdated(this); } } } public final void addListener(Listener listener) { synchronized (listeners) { listeners.add(listener); } } public final void removeListener(Listener listener) { synchronized (listeners) { listeners.remove(listener); } } }
Metode UpdateData () ditulis sehingga dibutuhkan beberapa waktu untuk mengeksekusi, yang dalam kehidupan nyata bisa menjadi permintaan ke server dan/atau perhitungan yang berat. Data tersebut disimpan terlindung dari akses konkuren menggunakan disinkronkan. Pendengar juga dapat ditambahkan dan dihapus dari benang bersamaan. Jika Anda benar-benar memahami MVC, Anda harus menyadari bahwa model pendengar adalah bagian inti dari pola - mereka, memungkinkan Anda untuk mengikat kode apapun untuk model tanpa model mengetahui apa-apa tentang hal itu (dan dengan demikian kode model menghindari setiap injeksi logika non-bisnis).
Part 2: Controller
Pada bagian ini Anda dapat menerapkan lapisan Pengendali dalam berbagai cara. Cara saya memilih untuk menyajikan didasarkan pada Handler , HandlerThread dan kelas Pesan. Pada intinya , dengan kelas-kelas platform Android memungkinkan Anda untuk menerapkan efektif , aman dan kuat pesan antara berbagai potongan aplikasi Anda.public class Controller { // ... some code omitted ... private final HandlerThread inboxHandlerThread; private final Handler inboxHandler; private final ListoutboxHandlers = new ArrayList (); // ... some code omitted ... public Controller(Model model) { this.model = model; inboxHandlerThread = new HandlerThread("Controller Inbox"); // note you can also set a priority here inboxHandlerThread.start(); // ... some code omitted ... inboxHandler = new Handler(inboxHandlerThread.getLooper()) { @Override public void handleMessage(Message msg) { Controller.this.handleMessage(msg); } }; } public final void dispose() { // ask the inbox thread to exit gracefully inboxHandlerThread.getLooper().quit(); } public final Handler getInboxHandler() { return inboxHandler; } public final void addOutboxHandler(Handler handler) { outboxHandlers.add(handler); } public final void removeOutboxHandler(Handler handler) { outboxHandlers.remove(handler); } final void notifyOutboxHandlers(int what, int arg1, int arg2, Object obj) { if (outboxHandlers.isEmpty()) { Log.w(TAG, String.format("No outbox handler to handle outgoing message (%d)", what)); } else { for (Handler handler : outboxHandlers) { Message msg = Message.obtain(handler, what, arg1, arg2, obj); msg.sendToTarget(); } } } // ... some code omitted ... }
Ini bukan kode lengkap untuk Controller, bagaimana kita menginisialisasi
dan menurunkan handler inbox dan benangnya, bagaimana Anda dapat
berlangganan handler Anda sebagai kotak keluar satu dan bagaimana Anda
memberitahu semua penangan kotak keluar dengan pesan.Dengan
kode ini, dapat mengambil handler inbox dan mengirim pesan ke
dari lapisan Lihat dan pada saat yang sama memiliki View terikat handler
terdaftar sebagai handler kotak keluar untuk Controller, dan yang akan
memungkinkan Controller dan View untuk pertukaran pesan async efektif. Sekarang
dalam rangka untuk benar-benar menangani pesan masuk dan melakukan
sesuatu, kita perlu menerapkan metode handleMessage() di kelas
Controller. Untuk menggambarkan bahwa, inilah antarmuka ControllerState dan implementasi readyState nya :
public interface ControllerState { boolean handleMessage(Message msg); } final class ReadyState implements ControllerState { private final Controller controller; public ReadyState(Controller controller) { this.controller = controller; } @Override public final boolean handleMessage(Message msg) { switch (msg.what) { case V_REQUEST_QUIT: onRequestQuit(); return true; case V_REQUEST_UPDATE: onRequestUpdate(); return true; case V_REQUEST_DATA: onRequestData(); return true; } return false; } private void onRequestData() { // send the data to the outbox handlers (view) controller.notifyOutboxHandlers(C_DATA, 0, 0, controller.getModel().getData()); } private void onRequestUpdate() { // we can't just call model.updateState() here because it will block // the inbox thread where this processing is happening. // thus we change the state to UpdatingState that will launch and manage // a background thread that will do that operation controller.changeState(new UpdatingState(controller)); } private void onRequestQuit() { controller.quit(); } }
dengan menempatkan controller paket yang sama, kita dapat memberikan mereka akses ke internal controller menggunakan tingkat akses default. sekarang inilah bagaimana delegasi pengendali pemprosesan pesan ke keadaan
public class Controller { // ... some code omitted ... private ControllerState state; public Controller(Model model) { this.model = model; // ... some code omitted ... this.state = new ReadyState(this); // ... some code omitted ... } // ... some code omitted ... private void handleMessage(Message msg) { Log.d(TAG, "Received message: " + msg); if (! state.handleMessage(msg)) { Log.w(TAG, "Unknown message: " + msg); } } final Model getModel() { return model; } final void quit() { notifyOutboxHandlers(C_QUIT, 0, 0, null); } final void changeState(ControllerState newState) { Log.d(TAG, String.format("Changing state from %s to %s", state, newState)); state = newState; } }
Part 3: View
View berfungsi untuk mengatur tampilan aplikasi
public class DemoActivity extends Activity implements Handler.Callback, OnClickListener { private static final String TAG = DemoActivity.class.getSimpleName(); private Controller controller; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ((Button) findViewById(R.id.update)).setOnClickListener(this); ((Button) findViewById(R.id.quit)).setOnClickListener(this); controller = new Controller(new Model()); controller.addOutboxHandler(new Handler(this)); // messages will go to .handleMessage() controller.getInboxHandler().sendEmptyMessage(V_REQUEST_DATA); // request initial data } @Override protected void onDestroy() { // I think it is a good idea to not fail in onDestroy() try { controller.dispose(); } catch (Throwable t) { Log.e(TAG, "Failed to destroy the controller", t); } super.onDestroy(); } @Override public boolean handleMessage(Message msg) { Log.d(TAG, "Received message: " + msg); switch (msg.what) { case C_QUIT: onQuit(); return true; case C_DATA: onData((ModelData) msg.obj); return true; case C_UPDATE_STARTED: onUpdateStarted(); return true; case C_UPDATE_FINISHED: onUpdateFinished(); return true; } return false; } private void onUpdateStarted() { ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar); progressBar.setVisibility(View.VISIBLE); } private void onUpdateFinished() { ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar); progressBar.setVisibility(View.GONE); // request the updated data controller.getInboxHandler().sendEmptyMessage(V_REQUEST_DATA); } private void onData(ModelData data) { TextView dataView = (TextView) findViewById(R.id.data_view); dataView.setText("The answer is "+ data.getAnswer()); } private void onQuit() { Log.d(TAG, "Activity quitting"); finish(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.update: controller.getInboxHandler().sendEmptyMessage(V_REQUEST_UPDATE); break; case R.id.quit: controller.getInboxHandler().sendEmptyMessage(V_REQUEST_QUIT); break; } } }
selain script di atas view di android juga merupakan tampilan layout yang biasa di simpan dalam format .xml seperti class di bawah ini
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/data_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:gravity="center"
style="@android:style/TextAppearance.Large"
android:text="" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="2.0">
<Button
android:id="@+id/update"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:text="Update" />
<Button
android:id="@+id/quit"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:text="Quit" />
</LinearLayout>
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone" />
</LinearLayout>
Tidak ada komentar:
Posting Komentar