07/09/2018, 18:17

Là một Android Developer thì bạn nhất định phải biết về Architechture Components.

1.Mở đầu. Vào tháng 11 năm 2017 Google đã đưa ra phiên bản Architechture Components 1.0 đầu tiên cho Android. Android Architechture Components là một bộ sưu tập các thư viện giúp các lập trình viên thiết kế các ứng dụng Android một cách mạnh mẽ, có thể dễ dàng test và maintain. Ban đầu là xây ...

1.Mở đầu.

Vào tháng 11 năm 2017 Google đã đưa ra phiên bản Architechture Components 1.0 đầu tiên cho Android. Android Architechture Components là một bộ sưu tập các thư viện giúp các lập trình viên thiết kế các ứng dụng Android một cách mạnh mẽ, có thể dễ dàng test và maintain. Ban đầu là xây dựng một số lớp dùng để quản lý vòng đời thành phần UI và xử lý data một cách bền vững, hiệu quả.

Ở bài viết này mình xin trình bày về tư tưởng và một cách tổng quan nhất về Architechture Components.

2.Why "Architechture" Components?

Câu hỏi đặt ra là Architechture Components được đưa ra để làm gì. Thì sau đây là các giá trị mà nó mang lại.

1.Persist Data: sử dụng data một cách bền vững, hiệu quả.

2.Manage Lifecycle: Quản lý vòng đời các thành phần cũng như ứng dụng.

3.Modular: Chia ứng dụng, thành phần thành các module nhỏ để dễ dàng quản lý.

4.Defense Against Common Errors: Phòng chống, hạn chế các lỗi thường gặp, như memory leaks chẳng hạn.

5.Less Boilerplate: tránh cho việc bạn viết code một cách nhàm chán.

Khi ứng dụng của bạn cần một Databse kết nối mạnh mẽ, tối ưu, hiệu quả với UI

Thì các Components mới như Room, ViewModel, LiveData, Lifecycle sẽ xử lý việc đó thật dễ dàng. Và 4 thành phần này được thiết kế để làm việc với nhau như một khối thống nhất. Chúng ta hay cùng lần lượt xem nhé.

3.Room.

Room là một thư viện ánh xạ đối tượng SQL mạnh mẽ. Bạn nên xử lý database sử dụng Room, nó được xem như là một SQLite mới. Để cài đặt các bảng sử dụng Room chúng ta phải định nghĩa một Plain Old Java Object (POJO - là gì thì các bạn có thể tự đọc lại nhé) :

    public class Trail {
        public String id;
        public String name;
        public double kilometers;
        public in difficult;
    }

sau đó đánh dấu nó với một @Entity anotation cùng với đánh dấu ID bằng @PrimaryKey annotation:

    @Entity
    public class Trail {
        public @PrimaryKey String id;
        public String name;
        public double kilometers;
        public in difficult;
    }

Với mỗi POJO bạn cần định nghĩa một DAO (Database Access Object):

    @Dao
    public interface TrailDao {
        //Create, read, update, delete examples.
        @Insert(onConflict == IGONE)
        void insertTrail(Trail trail);
    
        @Query("SELECT * FROM Trail")
        public List<Trail> findAllTrails();
    
        @Update(onConflict = REPLACE)
        void updateTrail(Trail trail);
    
        @Query("DELETE FROM Trail")
        void deleteAll();
    }

Các phương thức được chú thích để thể thiện lện trong SQLite mà bạn cần để tương tác với dữ liệu POJO của bạn. Bây giờ chúng ta hãy xem lại insert method:

        //Create.
        @Insert(onConflict == INGORE)
        void insertTrail(Trail trail);

và query method:

        //Query
        @Query("SELECT * FROM Trail")
        public List<Trail> findAllTrails();

Thì ta thấy Room đã tự động convert đối tượng POJO của bạn vào các bảng database tương ứng. Ngoài ra Room cũng xác minh SQLite tại thời điểm biên dịch. Vì vậy nếu bạn viết sai một cái gì đó, hoặc tham chiếu mà không có trong database thì nó sẽ báo lỗi. Bây giờ ứng dụng của bạn đã có một Room Database. Bạn có thể sử dụng một Component mới gọi là LiveData để theo dõi sự thay đổi trong Database:

Vậy LiveData là gì?

4.LiveData.

LiveData là một observable data holder, tức là đối tượng nắm giữ data và thông báo cho bạn khi có sự thay đổi data và lúc đó bạn có thể update UI. LiveData là một abstract class, bạn có thể kế thừa nó. Trong trường hợp đơn giản bạn có thể sử dụng MutableLiveData là một lớp con của nó:

    MutableLiveData<String> dayOfWeek = new MutableLiveData<>();
    dayOfWeek.observer(this, data -> {
        mTextView.setText(dayOfWeek.getValue() + "Thursday is good day for hike");
    });

Nếu bạn update giá trị của MutableLiveData bằng lời gọi set value, sau đó nó sẽ được kích hoạt và update trong UI:

    //Elsewhere in the code!
   dayOfWeek.setValue("Friday");

Room được built để support LiveData. Để sử dụng chúng với nhau, bạn chỉ cần thay đổi DAO để trả về các đối tượng đượng chứa trong lớp LiveData. Room sẽ tạo một LiveData dùng để lắng nghe, quan sát sự thay đổi dữ liệu của Database:

   @Dao
   public interface TrailDao {
       //Create, read, update, delete examples.
       @Insert(onConflict == IGNORE)
       void insertTrail(Trail trail);
   
       @Query("SELECT * FROM Trail")
       public LiveData<List<Trail>> findAllTrails();
   
       @Update(onConflict = REPLACE)
       void updateTrail(Trail trail);
   
       @Query("DELETE FROM Trail")
       void deleteAll();
   }

Sau đố bạn có thể viết code như thế này để cập nhật UI :

    trailsLiveData.observe(this, trails -> {
        //update UI, in this case a RecyclerView
        mTrailsRecyclerAdapter.replaceItems(trails);
        mTrailsRecyclerAdapter.notifyDataSetChanged();
    });

Kết quả cuối cùng mà Room Database update, nó sẽ thay đổi dữ liệu trong đối tượng LiveData, điều này sẽ tự động kích hoạt cập nhật giao diện UI. Điều này đã đưa chúng ta đến một tính năng tuyệt vời nữa của LiveData. LiveData là một lifecycle-aware component. Bây giờ bạn đã phải suy nghĩ vậy chính xác lifecycle-aware là gì?

5.Lifecycle.

Thông qua sự kì diệu của Lifecycle Observation, LiveData biết khi nào Activity của bạn đang là onScreen hay là offScreen hoặc Destroy và nó sẽ biết trạng thái nào nào cần cập nhật UI hoặc không cập nhật. Có 2 Interface thuộc lifecycle-aware là Lifecycle Owners and Lifecycle Observers.

Lifecycle Owners là những đối tượng có lifecycle (vòng đời) như Activity hoặc Fragment.

Lifecycle Observers quan sát hay lắng nghe Lifecycle Owners và nhận được thông báo về sự thay đổi của lifecycle (vòng đời).

Chúng ta hãy thử nhìn đoạn code dưới, code cho LiveData, nó cũng là một Lifecycle Observers.

    abstract public class LiveData<T> implements LifecycleObserver {
        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        void startup() {...}
        
        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        void cleanup() {...}
    }

Các phương thức với anotation @OnLifecycleEvent sẽ đánh dấu cho cho lúc khởi tạo hay kết thúc tương ứng với starts và stops trong Lifecycle Owner. Lúc này các UI Components sẽ quan sát, lắng nghe LiveData, còn LiveData quan sát, lắng nghe Lifecycle Owners.

Bây giờ bạn vẫn còn một vấn đề nữa để giải quyết. Ứng dụng của bạn sử dụng, nó sẽ đi qua các thay đổi cấu hình khác nhau. Như destroy rồi lại rebuild lại Activity. Chúng ta lại không muốn ràng buộc việc khởi tạo LiveData vào vòng đời Activity bởi vì sẽ tạo ra nhiều code được thực thi không cần thiết. Một ví dụ là khi bạn truy vấn database, việc này sẽ diễn ra mỗi lần khi bạn xoay màn hình chẳng hạn.

Vậy bạn nên làm gì, bạn có thể đặt LiveData hoặc bất kì dữ liệu nào liên kết với UI vào trong một ViewModel.

6.ViewModel.

ViewModel là một đối tượng cung cấp dữ liệu cho giao diện người dùng UI và nó tồn tại khi cấu hình ứng dụng thay đổi. Để tạo một đối tượng ViewModel, bạn extends lớp AndroidViewModel, sau đó bạn đưa dữ liệu cần thiết cho giao diện activity vào trong ViewModel.

    public class TrailListViewModel extends AndroidViewModel {
        private AppDatabase mDatabase;
        private LiveData<List<Trail>> trails;
        
        public TrailListViewModel(Application application) {
            supper(application);
            //AppDatabase is a Room database Singleton
            mDatabase = AppDatabse.getDb(getApplication());
            trails = mDatabase.trailModel().findAllTrails();
        }
        //Getters and Setters
    }

Khi bạn đã lưu dữ liệu cần thiết cho UI vào trong ViewModel. Ứng dụng cua bạn sẽ không truy vấn lại database nếu Activity khởi tạo lại trong khi cấu hình thay đổi. Sau đó khi bạn tạo Activity hoặc Fragment của bạn, bạn có thể lấy được một tham chiếu đến ViewModel và sử dụng nó.

    //In onCreate
    trailListViewModel = ViewModelProvides.of(this)
    .get(TrailListViewModel.class);
    
    //Code to set up the RecyclerView omitted
    trailListViewModel.getTrails().observe(this, trails -> {
        mTrailsRecyclerAdapter.replaceItems(trails);
        mTrailsRecyclerAdapter.notifyDataSetChanged();
    });

Lần đầu tiên bạn lấy ra ViewModel, nó được tạo cho Activity của bạn. Những lần tiếp theo bạn request ViewModel, Activity của bạn sẽ nhận được ViewModel ban đầu.

7.Tổng kết.

Để tóm tắt tất cả những kiến thức trên, chúng ta đã nói về:

Room, là một thư viện ánh xạ đối tượng dùng cho SQLite.

LiveData, đối tượng thông báo cho bạn sự thay đổi của data và bạn có thể update UI. Và rất quan trọng à nó làm việc tốt khi kết hợp với Room.

Lifecycle Observers and Owners : cho phép thành phần không UI lắng nghe sự kiện vòng đời của thành phần có UI.

ViewModel: Cung cấp data, là cái vẫn tồn tại khi cấu hình ứng dụng thay đổi.

Tất cả chúng là một tập hợp của Architechture Components dùng cho việc xây dựng ứng dụng một cách mạnh mẽ, và module hóa, dễ dàng test. Bạn có thể sử dụng chúng một cách hợp lý với nhau hoặc bạn có thể lựa chọn từng loại mà bạn cần. Nhưng đây chỉ là bề nổi của một ứng dụng, thực tế thì một ứng dụng đầy đủ phải có sơ đồ như dưới đây.

Như vậy, trên đây mình đã trình bày một cách tổng quan về Android Architechture Components. Có lẽ ở những bài viết tiếp theo mình xin đi chi tiết, cụ thể từng Component và sẽ mong được sự theo dõi của các bạn. Rất cám ơn!

8.

0