1. 程式人生 > >Android依賴注入框架三、AndroidAnnotations

Android依賴注入框架三、AndroidAnnotations

AndroidAnnotations是一個能夠讓你快速進行Android開發的開源框架,它能讓你專注於真正重要的地方。使程式碼更加精簡,使專案更容易維護。相比原生的Android App程式碼量,幾乎可以少一半。

用com.github.barteksc:android-pdf-viewer:2.8.1的demo中的PDFViewActivity.java為例,簡單對比AndroidAnnotations和ButterKnife兩個註釋框架。

/**
 * Copyright 2016 Bartosz Schiller
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.barteksc.sample;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.provider.OpenableColumns;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener;
import com.github.barteksc.pdfviewer.listener.OnPageChangeListener;
import com.github.barteksc.pdfviewer.listener.OnPageErrorListener;
import com.github.barteksc.pdfviewer.scroll.DefaultScrollHandle;
import com.hikvision.ivms87a0.R;
import com.hikvision.ivms87a0.function.KeyAct;
import com.shockwave.pdfium.PdfDocument;

import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.NonConfigurationInstance;
import org.androidannotations.annotations.OnActivityResult;
import org.androidannotations.annotations.OptionsItem;
import org.androidannotations.annotations.OptionsMenu;
import org.androidannotations.annotations.ViewById;

import java.util.List;

//import butterknife.BindView;
//import butterknife.ButterKnife;

@EActivity(R.layout.activity_pdf)//1.使用@EActivity,可以注入setContentView(R.layout.activity_pdf)
@OptionsMenu(R.menu.menu_pdf)//2.使用@OptionsMenu,可以注入onCreateOptionsMenu(Menu menu)
public class PDFViewActivity extends AppCompatActivity implements OnPageChangeListener, OnLoadCompleteListener,
        OnPageErrorListener {

    private static final String TAG = PDFViewActivity.class.getSimpleName();

    private final static int REQUEST_CODE = 42;
    public static final int PERMISSION_CODE = 42042;

    public static final String SAMPLE_FILE = "sample.pdf";
    public static final String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";

	@ViewById//3.使用@EActivity,作用與@BindView相同
    //@BindView(R.id.pdfView)
    PDFView pdfView;

	@NonConfigurationInstance //
[email protected]
Uri uri; @NonConfigurationInstance Integer pageNumber = 0; String pdfFileName; /*@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_pdf); ButterKnife.bind(this); afterViews(); }*/ private void initData() { String url = getIntent().getStringExtra(KeyAct.URL); uri = Uri.parse(url); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_pdf, menu); return super.onCreateOptionsMenu(menu); } @OptionsItem(R.id.pickFile)//5.使用@OptionsItem,可以注入onOptionsItemSelected(MenuItem item) void pickFile() { int permissionCheck = ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE); if (permissionCheck != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( this, new String[]{READ_EXTERNAL_STORAGE}, PERMISSION_CODE ); return; } launchPicker(); } /*@Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.pickFile: pickFile(); break; } return super.onOptionsItemSelected(item); }*/ void launchPicker() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("application/pdf"); try { startActivityForResult(intent, REQUEST_CODE); } catch (ActivityNotFoundException e) { //alert user that file manager not working Toast.makeText(this, R.string.toast_pick_file_error, Toast.LENGTH_SHORT).show(); } } @AfterViews//6.使用@AfterViews,作用與在onCreate(@Nullable Bundle savedInstanceState)中呼叫一樣 void afterViews() { initData(); pdfView.setBackgroundColor(Color.LTGRAY); if (uri != null) { displayFromUri(uri); } else { displayFromAsset(SAMPLE_FILE); } setTitle(pdfFileName); } private void displayFromAsset(String assetFileName) { pdfFileName = assetFileName; pdfView.fromAsset(SAMPLE_FILE) .defaultPage(pageNumber) .onPageChange(this) .enableAnnotationRendering(true) .onLoad(this) .scrollHandle(new DefaultScrollHandle(this)) .spacing(10) // in dp .onPageError(this) .load(); } private void displayFromUri(Uri uri) { pdfFileName = getFileName(uri); pdfView.fromUri(uri) .defaultPage(pageNumber) .onPageChange(this) .enableAnnotationRendering(true) .onLoad(this) .scrollHandle(new DefaultScrollHandle(this)) .spacing(10) // in dp .onPageError(this) .load(); } @OnActivityResult(REQUEST_CODE)//6.使用@OnActivityResult,作用與下方的onActivityResult(int requestCode, int resultCode, Intent data)相同 public void onResult(int resultCode, Intent intent) { if (resultCode == RESULT_OK) { uri = intent.getData(); displayFromUri(uri); } } /*@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_CODE: onResult( resultCode, data); break; default: break; } }*/ @Override public void onPageChanged(int page, int pageCount) { pageNumber = page; setTitle(String.format("%s %s / %s", pdfFileName, page + 1, pageCount)); } public String getFileName(Uri uri) { String result = null; if (uri.getScheme().equals("content")) { Cursor cursor = getContentResolver().query(uri, null, null, null, null); try { if (cursor != null && cursor.moveToFirst()) { result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); } } finally { if (cursor != null) { cursor.close(); } } } if (result == null) { result = uri.getLastPathSegment(); } return result; } @Override public void loadComplete(int nbPages) { PdfDocument.Meta meta = pdfView.getDocumentMeta(); Log.e(TAG, "title = " + meta.getTitle()); Log.e(TAG, "author = " + meta.getAuthor()); Log.e(TAG, "subject = " + meta.getSubject()); Log.e(TAG, "keywords = " + meta.getKeywords()); Log.e(TAG, "creator = " + meta.getCreator()); Log.e(TAG, "producer = " + meta.getProducer()); Log.e(TAG, "creationDate = " + meta.getCreationDate()); Log.e(TAG, "modDate = " + meta.getModDate()); printBookmarksTree(pdfView.getTableOfContents(), "-"); } public void printBookmarksTree(List<PdfDocument.Bookmark> tree, String sep) { for (PdfDocument.Bookmark b : tree) { Log.e(TAG, String.format("%s %s, p %d", sep, b.getTitle(), b.getPageIdx())); if (b.hasChildren()) { printBookmarksTree(b.getChildren(), sep + "-"); } } } /** * Listener for response to user permission request * * @param requestCode Check that permission request code matches * @param permissions Permissions that requested * @param grantResults Whether permissions granted */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { if (requestCode == PERMISSION_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { launchPicker(); } } } @Override public void onPageError(int page, Throwable t) { Log.e(TAG, "Cannot load page " + page); } }

從上面的程式碼可以看出,用@EActivity、@ViewById、@AfterViews、@Click等註解來完成元件的建立、初始化和點選等操作。含義如下:

@EActivity
必須要有一個layout id來表示這個Activity所使用的佈局,用來替代setContentView的操作。
@ViewById
和原來的findViewById()方法一樣,後面可以跟上每個view id,用來替代元件的初始化操作,值得注意的是:@ViewById後的id是可以不寫的,條件是元件變數名稱要與xml中定義的id必須一致(方法2)。
@AfterViews 
表示在元件初始化完成後在執行,更新元件狀態的方法必須加上這個註解,否則會出現空指標。
注意:新增@EActivity(R.layout.XXX)的時候如果沒有刪除`onCreate(Bundle savedInstanceState)`中的layout配置,activity會進行兩次佈局,導致執行兩次配置@AfterViews註解的方法。 
@Click 
表示點選事件,用來完成元件的點選事件的操作。

參考:link1