搜尋此網誌

2014-03-12

Query file type in Windows

Linux 裡有個好用的檔案格式檢查工具「file」。
但,Windows 並沒有內建這個功能,
以下介紹如何在 Windows 中使用它。

2013-12-02

Loading Large Bitmaps Efficiently

KH.Chen
 
 
這篇文章還有分享一些catch跟清除memory的方法,不過那是用在listView跟gridView的,
我目前用的viewPager看來並不適合,所以我說明會著重在怎樣載入bitmap是比較恰當的。
 
首先假設我們有一個fragment,inflate這個fragment的時候我們設計了一個layout xml,
其中有一個imageView,我們要將某張照片載入到這個imageView,流程應該是怎樣?
 
1.取得ImageView的height跟weight,要如何取得呢?簡單的程式碼如下:
  DisplayMetrics dm = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(dm);
        mScreenWidth = dm.widthPixels; // width
        mScreenHeight = dm.heightPixels;// height
 
上面的程式碼就可以拿到這支手機的屏幕解析度,你再依照layout的weight去算即可
 
2.壓縮bitmap,要怎樣壓縮bitmap讓imageView的畫質跟讀取速度取得平衡?
請看下面的程式碼:
 
    public static Bitmap decodeSampledBitmapFromFile(String filePath, int reqWidth, int reqHeight) {
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }
 
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.

            while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }
 
簡單說就是先算出這張bitmap的原始height跟width,再跟imageView的height跟width做比較
再用他寫的演算法,算出來inSampleSize的倍率要多少,這樣就是最適合此imageView的
bitmap壓縮結果。
 
 
3.display to UI:那要如何將這張bitmap顯示到UI上面呢?要是寫在main thread的話,bitmap太大,勢必會讓手機停頓延遲,這樣使用者就會覺得lag,爛程式,所以我們要用另一個thread
來讀取,最簡單的方法就是開一個asyncTask,當bitmap讀完的時候再更新UI,大概就是下面這樣
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String... params) {
//在這邊拿到要設定bitmap的參數
            filePath = params[0];
            return decodeSampledBitmapFromFile(filePath, mScreenWidth, mScreenHeight);
        }
 
protected void onPostExecute(Bitmap bitmap) {
//在這邊判斷一下bitmap是否為null,更新main UI的imageView
            if (imageViewReference != null && bitmap != null) {
                final ImageView imageView = imageViewReference.get();
                if (imageView != null) {
                    imageView.setScaleType(ScaleType.CENTER);
                    imageView.setImageBitmap(bitmap);
                }
            }
 }
 
還有最後提醒一下,imageView能用setImageResource,就不要用setImageBitmap,兩者的速度
差別是天跟地,bitmap是取得外部的resource用的,一些內建有的圖檔就用setImageResource就好,這個viewPager performance的改善花了我很多時間,分享給大家,還有如果是用listView或是gridView這種大量的bitmap,那一定還需要自己實做memory release跟catch機制,裡面也有寫道,ViewPager是自己會delete沒有用到的fragment,所以比較沒有這個問題。
 

2013-11-22

當View沒有對映的method可以設定屬性時...



想在程式裡建立一個EditText, 並設定cursorDrawable, 但我們new EditText所取得的instance裡並沒有對應可以set CursorDrawablemethod, 而只在xml可以設定android:textCursorDrawable屬性, 這時我們就可以用這種解決方法.

AttributeSet editTextAttributeSet = null;
int res = context.getResources().getIdentifier("cust_edittext", "layout", context.getPackageName());
XmlPullParser parser = context.getResources().getXml(res);
int state=0;
do {
    state = parser.next();
    if (state == XmlPullParser.START_TAG) {
        if (parser.getName().equals("EditText")) {
            editTextAttributeSet = Xml.asAttributeSet(parser);
            break;
        }
    }
} while(state != XmlPullParser.END_DOCUMENT);


然後要使用時只要代入AttributeSet就可以了
EditText edittext = new EditText(context, editTextAttributeSet);

上面紅字部分有個cust_edittext其實就是一個EditTextxml, 例如在layout/cust_edittext.xml
這樣我們就可以設定CursorDrawable
<?xml version="1.0" encoding="utf-8"?>
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textCursorDrawable="@null"
        android:textColor="#ff000000">       
</EditText>

2013-11-01

Strong Reference and Weak Reference

在 Java 中關於Reference,一般說來分為四種:Strong、Soft、Weak 和 Phantom 。

為什麼 Java 需要四種不同的 Reference 呢?

因為 Java 不像 C/C++ 需要設計師自行管控和釋放記憶體,而是透過 Garbage collector 檢查記憶體 (Heap) 中的 Object reference count / reachability 來決定是否要回收該記憶體以供他處使用, 而這垃圾回收機制(Garbage Collection) 需要知道那些記憶體該被回收、其回收的優先順序為何,所以 Java 提供了四種不同的 reference type 以便進行演算來得知。

Garbage collector 回收記憶體 (Heap) 時,將依據不同的 reference type 的強弱來決定其順序,以下是一個由強至弱的排序:

Strong Reference > Soft Reference > Weak Reference > Phantom Reference

2013-10-28

AIDL and Remote Service

作者: Joy Song

基於安全上的考量,Android的每個AP都會跑在自己的process上,不同的process是無法直接溝通的,必須要透過Android所提供的某些機制 (Intent, Binder) 才能達到溝通的訊息。

因此,Android提供了一種IPC的實作方式AIDL來達到讓兩個不同process也能相互溝通的目的。實作的方法很簡單,以下提供一個簡單的範例,另外AIDL有些要注意的地方,這邊也提出來跟大家分享。

實作範例


1. 定義 aidl 檔案


Context 是什麼?

作者:KH Chen

Context在很多地方都會用到,但是他到底有哪些限制?你現在拿到的Context真的是你想要的Context嗎?我們在開發APP常常會用到Context,但是在使用上我們卻常常忽略了一件事情:

One Context is not equal to another!!!

讓我們來看看下列表格:

ApplicationActivityServiceContentProviderBroadcastReceiver
Show a DialogNOYESNONONO
Start an ActivityNO1YESNO1NO1NO1
Layout InflationNO2YESNO2NO2NO2
Start a ServiceYESYESYESYESYES
Bind to a ServiceYESYESYESYESNO
Send a BroadcastYESYESYESYESYES
Register BroadcastReceiverYESYESYESYESNO3
Load Resource ValuesYESYESYESYESYES

2013-10-25

AsyncTask 的黑暗面

作者:囧尼

相信Android App的開發者對於使用AsyncTask肯定不陌生,它提供了一個在背景運算操作又同時能夠更新結果至UI thread的方式。但有幾個小地方可能開發者會容易忽略而導致一些不可預期的結果發生。

Lifecycle


很多人可能認為若在Activity中創建了一個AsyncTask,那當該 Activity被destroyed 時,理論上這個AsyncTask也應該被刪除了才是。答案是錯,這個AsyncTask會繼續在背景執行它的doInBackground(),而這樣的問題會導致Crash的發生,因為它想要refer的一些物件早已經不存在了。

所以我們必須要確認在destroyed Activity的同時,有去取消 (cancel) AsyncTask 掉。呼叫cancel(boolean mayInterruptRunning)來cancel這個task,這個boolean值為true的話,代表當前的task應該立即被中斷,反之則允許處理完當前事務後結束。如果在doInBackground()中有使用道loop的話,建議可以每次呼叫isCancelled()方法來避免掉多餘的處理。