12/08/2018, 11:14

thư viện sử dụng annotation để less code trong andoid

Bài viết này mình không đề cập đến hiệu suất. Bài viết chỉ giới thiệu làm sao code ít hơn, thời gian con lại chúng ta có thể fix bug nghe nhạc vv.v.v Cái gì càng đơn giản thì đôi khi phí sâu càng phức tạp. Đương nhiên để code ít hơn không phải vì android có những function, class .... gì đó ngắn ...

Bài viết này mình không đề cập đến hiệu suất. Bài viết chỉ giới thiệu làm sao code ít hơn, thời gian con lại chúng ta có thể fix bug nghe nhạc vv.v.v

Cái gì càng đơn giản thì đôi khi phí sâu càng phức tạp. Đương nhiên để code ít hơn không phải vì android có những function, class .... gì đó ngắn ngọn hơn. Mà ở đây chủ yếu dựa vào đặc tính Java annotation. Bản thân mình cũng có thể viết ra thư viện sử dụng annotation, nhưng việc đó lại mất rất nhiều thời gian.

Bài viết sẽ giới thiệu và hướng dẫn sử dụng một số thư viện nổi tiếng hiện nay nhằm giúp anh em. code ít hơn, hiệu quả hơn ^^

  1. VIEWS Như anh em cũng biết việc khai báo đối tượng Textview, ImageView.... trong Activity thật vất vả và mất nhiều thời gian. Chủ yếu cũng toàn copy code thôi. nhưng khi nhìn vào code thấy nhiều dòng khai báo thừa thãi. khiến mã nguồn rối rắm.
  • Butterknife (http://jakewharton.github.io/butterknife/) Mình giới thiệu và hướng dẫn cái này đầu tiên. vì nó rất đơn giản. thư viện cũng bé ít class, hiệu suất cao. Và nó chủ yếu tập trung bind View. chư không bind nhiều Object khác trong android

Thông thường khi khởi tạo các view trong Activity

    private  DrawerLayout drawerLayout;
    private  Toolbar toolbar;
    private  NavigationView navigationView;
    private  Button btnSubmit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		//Đoạn này khá thừa thãi
        drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        navigationView = (NavigationView) findViewById(R.id.navigationView);
        btnSubmit = (Button) findViewById(R.id.submit);

        btnSubmit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
         ...............

    }

Khi sử dụng Butterknife

    @Bind(R.id.drawerLayout)    DrawerLayout drawerLayout;
    @Bind(R.id.toolbar)         Toolbar toolbar;
    @Bind(R.id.navigation)      NavigationView navigationView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        drawerLayout.setOn.....
         ...............

    }

    @OnClick(R.id.submit)
	public void submit(View view) {
  	// Hành động .....
	}

-> Chúng ta chỉ cần code những thứ cần thiết

  • Androidannotations (http://androidannotations.org/)
public class BookmarksToClipboardActivity extends Activity {

  BookmarkAdapter adapter;

  ListView bookmarkList;

  EditText search;

  BookmarkApplication application;

  Animation fadeIn;

  ClipboardManager clipboardManager;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN);

    setContentView(R.layout.bookmarks);

    bookmarkList = (ListView) findViewById(R.id.bookmarkList);
    search = (EditText) findViewById(R.id.search);
    application = (BookmarkApplication) getApplication();
    fadeIn = AnimationUtils.loadAnimation(this, anim.fade_in);
    clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);

    View updateBookmarksButton1 = findViewById(R.id.updateBookmarksButton1);
    updateBookmarksButton1.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View v) {
        updateBookmarksClicked();
      }
    });

    View updateBookmarksButton2 = findViewById(R.id.updateBookmarksButton2);
    updateBookmarksButton2.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View v) {
        updateBookmarksClicked();
      }
    });

    bookmarkList.setOnItemClickListener(new OnItemClickListener() {

      @Override
      public void onItemClick(AdapterView<?> p, View v, int pos, long id) {
        Bookmark selectedBookmark = (Bookmark) p.getAdapter().getItem(pos);
        bookmarkListItemClicked(selectedBookmark);
      }
    });

    initBookmarkList();
  }

  void initBookmarkList() {
    adapter = new BookmarkAdapter(this);
    bookmarkList.setAdapter(adapter);
  }

  void updateBookmarksClicked() {
    UpdateBookmarksTask task = new UpdateBookmarksTask();

    task.execute(search.getText().toString(), application.getUserId());
  }

  private static final String BOOKMARK_URL = //
  "http://www.bookmarks.com/bookmarks/{userId}?search={search}";

  class UpdateBookmarksTask extends AsyncTask<String, Void, Bookmarks> {

    @Override
    protected Bookmarks doInBackground(String... params) {
      String searchString = params[0];
      String userId = params[1];

      RestTemplate client = new RestTemplate();
      HashMap<String, Object> args = new HashMap<String, Object>();
      args.put("search", searchString);
      args.put("userId", userId);
      HttpHeaders httpHeaders = new HttpHeaders();
      HttpEntity<Bookmarks> request = new HttpEntity<Bookmarks>(httpHeaders);
      ResponseEntity<Bookmarks> response = client.exchange( //
          BOOKMARK_URL, HttpMethod.GET, request, Bookmarks.class, args);
      Bookmarks bookmarks = response.getBody();

      return bookmarks;
    }

    @Override
    protected void onPostExecute(Bookmarks result) {
      adapter.updateBookmarks(result);
      bookmarkList.startAnimation(fadeIn);
    }

  }

  void bookmarkListItemClicked(Bookmark selectedBookmark) {
    clipboardManager.setText(selectedBookmark.getUrl());
  }

}

Sau khi sử dụng

@NoTitle
@Fullscreen
@EActivity(R.layout.bookmarks)
public class BookmarksToClipboardActivity extends Activity {

  BookmarkAdapter adapter;

  @ViewById
  ListView bookmarkList;

  @ViewById
  EditText search;

  @App
  BookmarkApplication application;

  @RestService
  BookmarkClient restClient;

  @AnimationRes
  Animation fadeIn;

  @SystemService
  ClipboardManager clipboardManager;

  @AfterViews
  void initBookmarkList() {
    adapter = new BookmarkAdapter(this);
    bookmarkList.setAdapter(adapter);
  }

  @Click({R.id.updateBookmarksButton1, R.id.updateBookmarksButton2})
  void updateBookmarksClicked() {
    searchAsync(search.getText().toString(), application.getUserId());
  }

  @Background
  void searchAsync(String searchString, String userId) {
    Bookmarks bookmarks = restClient.getBookmarks(searchString, userId);
    updateBookmarks(bookmarks);
  }

  @UiThread
  void updateBookmarks(Bookmarks bookmarks) {
    adapter.updateBookmarks(bookmarks);
    bookmarkList.startAnimation(fadeIn);
  }

  @ItemClick
  void bookmarkListItemClicked(Bookmark selectedBookmark) {
    clipboardManager.setText(selectedBookmark.getUrl());
  }

}

Ngoài ra còn nhiều thư viện mạnh hơn, hỗ trợ nhiều đối tượng hơn

  1. GSON Gson là một thư viện Java mà có thể được sử dụng để chuyển đổi các đối tượng Java thành chuỗi JSON. Nó cũng có thể được sử dụng để chuyển đổi một chuỗi JSON để thành một đối tượng Java tương đương
class BagOfPrimitives {
  private int value1 = 1;
  private String value2 = "abc";
  private transient int value3 = 3;
  BagOfPrimitives() {
    // no-args constructor
  }
}

(Serialization)
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
==> json is {"value1":1,"value2":"abc"}

Tham khảo thêm https://sites.google.com/site/gson/gson-user-guide

  1. Restful api

Việc khai báo các đối tượng, khởi tạo http... rồi paser đối đượng vào object v.v.v.khi trọng dự and có kết nối đến server sử dụng restfull api đôi khi rất mất thời gian và dễ nhầm .

Để việc đó hiệu quả hơn và giành thời gian cho vấn đề logic ... thì mình xin giới thiệu thư viện

Retrofit (http://square.github.io/retrofit/)

Sử dụng annotations để mô tả các HTTP request: (Nguyên văn TA) -URL parameter replacement and query parameter support -Object conversion to request body (e.g., JSON, protocol buffers) -Multipart request body and file upload

Trong dự án hiện ại mình đang sử dụng.

Để khai báo Service rất đơn giản

public interface SlimoService {
    @GET("/user")  // dùng để get thông tin user
    void getUser(SlimCallback<SlimResponse<User>> callback);

    @POST("/users") // Để đăng ký 1 user
    void registerUser(@Body User user, SlimCallback<SlimResponse<User>> callback);
}

Các method được hỗ trợ đầy đủ GET, POST, PUT, DELETE, và HEAD

Cài đặt

       Gson gson = new GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                .registerTypeAdapter(SlimResponse.class, new SlimDeserializer())  // Bạn không cần làm điều này nếu không muốn tạo ra chuẩn Response theo ý mình
                .create();

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(BuildConfig.SERVER_ENDPOINT) // http://api.demo.com
                .setClient( new OkClient(new OkHttpClient())) // mình có sử dụng network layer là okhttp
                .setConverter(new GsonConverter(gson))
                .setErrorHandler(new CustomErrorHandler(getApplicationContext())) // Tạo ra thông báo riêng cho app
                .build();

         SlimService slimService = restAdapter.create(SlimService.class);

Sử dụng lấy thong tin một

slimService.getUser(new SlimCallback<SlimResponse<User>>() {
                @Override
                public void success(SlimResponse<User> userSlimResponse) {
                    User userInfo = userSlimResponse.getData();
                    // User lấy được
                }

                @Override
                public void failure(ErrorResponse errorResponse) {
                // Lỗi
                }

            });

Nếu project các bạn có sử dụng nhưng thư viện trên, nếu có sự cố hãy liên hệ mình. hi vọng mình sẽ giải đáp được phần nào

Hiện tại android đã hỗ trợ DATA BINDING

Để sử dụng B1: cài đặt môi trường. thêm vào build.gradle

apply plugin: 'com.android.application'
apply plugin: 'com.android.databinding'

  dependencies {
       classpath "com.android.tools.build:gradle:1.3.0-beta4"
       classpath "com.android.databinding:dataBinder:1.0-rc1"
   }

allprojects {
   repositories {
       jcenter()
   }
}

Code trong Java

public class User {
   public final String firstName;
   public final String lastName;
   public User(String firstName, String lastName) {
       this.firstName = firstName;
       this.lastName = lastName;
   }
}

........

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
   User user = new User("Test", "User");
   binding.setUser(user);
}

Code Layout

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_awidth="match_parent"
       android:layout_height="match_parent">
       <TextView android:layout_awidth="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.firstName}"/>
       <TextView android:layout_awidth="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.lastName}"/>
   </LinearLayout>
</layout>
0