Android編程小技巧

1、我們有時會遇到如下問題。當有兩個或多個UI類展示界面大體相同,但需要展示不同的內容,並且這些類之間都要相互交換或者刷新數據。繁瑣的做法是爲每一個UI類都建立新的佈局,這樣便出現了很多冗餘佈局,當它們之間需要交換業務時,直接把這些類的引用到處傳遞也是很頭疼的事情,這時可用抽象了類來解決這個問題。當然,Fragement完全可以實現這樣的功能,但也有它所不能施展的地方。
例:
有三個頁面展示的類,爲FirstUI、SecondUI、ThirdUI,它們所展示的頁面分爲三個部分,分別是標題欄,內容展示欄,底部狀態欄,這時可將這三個部分抽取到抽象類中,在實現類裏實現中間類型的動態加載以及對上下狀態欄的數據刷新(這裏沒提取公共View,而是放到了各個管理器裏了)。
代碼如下:
抽象父類:

public abstract class BaseUI implements OnclicListener{
    private Context context;

    public BaseUI(Context context){
        this.context = context;
    }
    //獲取展示界面
    public abstract View getChild();
    //標識是哪一個界面
    public abstract int getID(); 
    @Override
    public void onClick(View v) {
    //並不是所有的界面都需要有點擊事件,需要用到時,在複寫這個方法
    }
}

然後FirstUI類如下,其餘不在鰲訴:

public class FirstUI extends BaseUI {

    private Context context;
    private TextView view;

    public FirstUI(Context context) {
        super(context);
        this.context = context;
        init();
    }

    public void init(){
        view = new TextView(context);
        LayoutParams params = view.getLayoutParams();
        params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
        view.setLayoutParams(params);
        view.setBackgroundColor(color.green);
        view.setText("This is a first page!");
    }

    public View getChild() {
        return view;
    }

    @Override
    public int getID() {
    // TODO Auto-generated method stub
    return Constant.VIEW_FIRST; //建議將這個ID類型放在常量類中,便於統一管理
    }
}

而在進行用戶界面切換時,不需要給出具體實現類,可以採用字節碼,而字節碼
也不是任何類型都可以傳遞進來的,應該只能是BaseUI類的子類。

public void changeUI(Class<? extends BaseUI> targetClazz) {
String key = targetClazz.getSimpleName();//獲取類名
        if (viewAche.containsKey(key)) {
            targetUI = viewAche.get(key);
        } else {
            try {
                //得到他的構造器
                Constructor<? extends BaseUI> constructor = targetClazz
                        .getConstructor(Context.class);
                targetUI = constructor.newInstance(getContext());
                viewAche.put(key, targetUI);
            } catch (Exception e) {
                throw new RuntimeException("BaseUI Constructor Error!");
            }
        }
}

2、當有多個容器各自管理着自己的任務,當某個容器內容變化後,與之相聯繫的容器也應當變化,傳統的方式是在需要變化的容器內部進行更改,這樣做之後會增大它們之間的耦合度,此時可以採用觀察者模式進行解耦,當數據需要更改時,通知觀察者改變數據。
具體做法,可以採用Java類庫裏的Observable類,也可以自己寫一個這樣的類(不建議哦!你對自己的編碼能力是否有信心),繼承它!

//繼承已有工具類Observable
public class MiddleManager extends Observable {
    private MiddleManager() {
    }
}
private void change() {     
    // 觀察者模式,改變監聽狀態,通知觀察者數據改變了
    this.setChanged();
    //otherClass已註冊的類的ID
    this.notifyObservers(otherClass.getID());
}

添加觀察的對象。

private void init() {
    TitleManager manager = TitleManager.getInstance();
    manager.init(this);
    manager.showLoginTitle();

    BottomManager bottom=BottomManager.getInstrance();
    bottom.init(this);
    bottom.showCommonBottom();

    MiddleManager middle = MiddleManager.getInstance();
    middle.setMiddle(ii_middle);
    middle.changeUI(HallViewPager.class);

    //觀察者模式,添加觀察者
    middle.addObserver(manager);
    middle.addObserver(bottom);
}

被觀察者實現Observer接口,更新數據

//實現Obserever接口,實現Observer的方法
public class TitleManager implements Observer{
@Override
public void update(Observable observable, Object data) {
//乾點壞事,別人都不知道
}
}

3、如果一個組件想要得到當前上下文,可以組件自身來獲取。如下:
middle是一個Linearlayout,這樣做可以防止當前上下文到處傳遞引用,避免造成內存泄漏。

public class ClassTemp{
    //同過組件自身獲得當前上下文
    public Context getContext() {
           return middle.getContext();
    }
    //通過view自己的父親那裏得到移除的方法,把自己幹掉,就是自殺
    public void init(LinearLayout view){
       ViewGroup parent=(ViewGroup)view.getParent();
       parent.removeView(view);
    }
}

4、當使用LinearLayout佈局時,發現(圖.1)中的情況,這說明佈局文件填充全部寬度沒有起作用,導致的原因是root爲空的時候,它不會設置LayoutParams。做法是自己去填充一下。代碼如下:

showInMiddle = (LinearLayout) View.inflate(context, R.layout.il_hall1,
                null);
        if (showInMiddle.getLayoutParams() == null) {
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT);
            showInMiddle.setLayoutParams(params);
        }

 圖 1 手機界面未填充滿效果圖(盜圖)

                    圖 1 手機界面未填充滿效果圖(盜圖)

5、動態更改ListView的孩子,不影響已經加載的item。
首先爲每一個item設置一個tag:
holder.iv_news.setTag(position);
得到要更新的組件:
TextView view = listview.findViewWithTag(position);
進行更新即可;

6、當在GridView中顯示很多個相同的圖片,而只是裏面的文字不同,比如彩票的號碼,他們的背景圖片都一樣,只是它們顯示的文字不一樣,那麼我們可以用TextView來填充,不用將每張圖片都畫一遍,那樣做的代價是很
大的,例子如下:

@Override
    public int getCount() {
        // TODO Auto-generated method stub
        return endNum;    //你要顯示的球的個數
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        **TextView view = new TextView(context);
        DecimalFormat decimalFormat = new DecimalFormat("00");
        view.setText(decimalFormat.format(position + 1));
        view.setBackgroundResource(R.drawable.id_defalut_ball);
        view.setTextSize(16);
        view.setGravity(Gravity.CENTER);**
        return view ;
    }

7、當有多個TextView要顯示,並且顏色還不一樣,可以用fromHtml進行轉化,就不需要寫那麼的TextView了,例如:
定義數據:

<![CDATA[注數:&#160;&#160;<font color="#ff0000">NUM</font>&#160;&#160;注&#160;&#160;金額:&#160;&#160;<font color="#ff0000">MONEY</font>元]]>
String noticeInfo = context.getResources().getString(
                R.string.is_shopping_list_notice);
        noticeInfo = StringUtils.replaceEach(noticeInfo, new String[] { "NUM",
                "MONEY" }, new String[] { lotterynumber.toString(),
                lotteryvalue.toString() });

        // Html.fromHtml(notice):將notice裏面的內容轉換
        notice.setText(Html.fromHtml(noticeInfo));

8、當在做一個手機端程序,需要上傳數據到網絡,但又苦於用戶可能沒有網絡,此時可以採用離線上傳的做法。
首先,在本地數據庫保存數據,用戶每上傳成功一條,你都要記錄到本地數據庫,已實現數據同步,但又要避免不斷髮送和接受重複數據,導致用戶流量增加。此時,可以在設計數據庫時設計兩個表,一個是本地緩存表,一個是待上傳的數據表,每上傳成功一個就刪去待上傳數據表中的數據。這種做法如同凍結資金錶。

9、項目使用的配置文件(bean.properties)必須跟隨在src目錄下。

10、圖片中紅色框裏的東西代表,當把apk文件變爲jar包的時候,讓程序去自動管理資源文件的ID,不勾選會出現很蛋疼的問題(資源文件命名規則很重要)。

圖2 eclispse創建工程界面

                            圖2 eclispse創建工程界面

11、Android中點擊圖標不顯示activity界面的辦法,在清單文件裏設置系統主題不顯示界面(鎖屏軟件用得上哦)。

 android:theme="@android:style/Theme.NoDisplay" />

12、建立殺不死的服務。這個有點狠,違背道德啊!僅供學習測試參考,開發人員慎用,出現後果自負,與本小編無關。
(1)進程守護
創建連個相同的服務,在
@Override
public void onDestroy() {}
方法裏對另外一個服務啓動,反過來相同,便可以達到目的

(2)廣播接收者
用廣播監聽各種廣播事件,當這個時間發生後,便會啓動這個服務;

13、Android引用資源位圖更改大小方法 。

//以Drawable取得資源裏的圖片
Drawable drawable = this.getResources().getDrawable(R.drawable.white);
//設置位圖的大小與位置
  drawable.setBounds(0, 0, pointSize, pointSize);
  //創建一個內容爲空的位圖對象,這個位圖對象在內存裏是空的,並沒有什麼內容
Bitmap bitmap = Bitmap.createBitmap(pointSize, pointSize, Config.ARGB_8888);
//創建一個畫布,將上面創建的位圖畫在這個畫布上,此時這個畫布也是空的,並沒有什麼東西  
Canvas can = new Canvas(bitmap);
//調用Drawable自身的draw方法,將它自己畫在剛纔創建的額畫布上
  drawable.draw(can);

//最候,便可以得到自己想要多大並且可以在人員位置繪畫的drawable資源裏的圖片
canvas.draw(bitmap,x,y,paint);

14、如何選擇最佳存儲選項。
(1)如果數據可以使用鍵/值對來標識,那麼久使用SharedPreferences對象。
(2)如果需要存儲臨時數據,勇士內部存儲器是一個很好的選擇。
(3)有時需要和其他用戶共享應用 程序數據,這時候可以將文件存儲在設備上的SD卡上。

15、讓文本框獲得焦點,但不顯示輸入法面板。


 <activity
            android:name="com.example.autoui.MainActivity"
            android:label="@string/app_name"
           android:windowSoftInputMode="stateHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
  </activity>

16、使用Collections.sort(*,*)實現對數據的亂序處理。參數“T”代表你的數據類型,需要傳入List對象。

Collections.sort(new ArrayList<T>(), new Comparator<T>() {

            @Override
            public int compare(T lhs, T rhs) {
            //因爲你永遠無法知道它返回的是1還是-1,所以在比較時也無法
            //知道誰大誰小,達到亂序的可能;
                return Math.random() > 0.5 ? 1 : -1;
            }
        });

17、從圖庫(gallery)獲取一張圖片。

Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
//獲取image的uri
Uri imageFileUri = intent.getData(); 
//bmpFactoryOptions 圖片的Options,直接加載到內存可能會OOM哦
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().
openInputStream(imageFileUri), null, bmpFactoryOptions);

18、獲取圖片文件獲取Exif信息。

//從文件獲取exif信息
ExifInterfaceei = new ExifInterface(imageFilePath);
String imageDescription = ei.getAttribute("ImageDescription");
if (imageDescription != null)
{
Log.v("EXIF", imageDescription);
}

//把exif信息寫到文件:
ExifInterfaceei = new ExifInterface(imageFilePath);
ei.setAttribute("ImageDescription","Something New");

19、獲取手機網卡mac地址,記得加權限。

//權限
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> 

private String getLocalMacAddress() {  

    WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);  

    WifiInfo info = wifi.getConnectionInfo();  

    return info.getMacAddress();  

  } 

本人初出茅廬,文中難免有錯誤之處,還望指正,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章