Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android中反射技術使用實例

android中反射技術使用實例

編輯:關於Android編程

在計算機科學領域,反射是指一類應用,它們能夠自描述和自控制。也就是說,這類應用通過采用某種機制來實現對自己行為的描述(self-representation)和監測(examination),並能根據自身行為的狀態和結果,調整或修改應用所描述行為的狀態和相關的語義.反射 是 Java 程序開發語言的特征之一,它允許運行中的 Java 程序對自身進行檢查,或者說“自審”,並能直接操作程序的內部屬性。Java 的反射機制的實現要借助於4個類:class,Constructor,Field,Method;其中class代表的時類對 象,Constructor-類的構造器對象,Field-類的屬性對象,Method-類的方法對象。

1.通過反射技術可以訪問到其他包名下數據方法等,這些為一些APK換皮膚提供了方便

首先初始化skinContext


 try {  
            skinContext = this.createPackageContext("com.skin",   
                    CONTEXT_IGNORE_SECURITY|CONTEXT_INCLUDE_CODE);  
        } catch (NameNotFoundException e) {  
            // TODO Auto-generated catch block  
            skinContext=null;  
            e.printStackTrace();  
        }  

可以通過下面的方法訪問到指定包名下的資源ID
/** 
     * 取得對應包的所有資源的ID 
     * 存在MAP中 
     * @param packageName 
     * @return 
     */  
    private Map> getSkinResourcesId(String packageName)  
    {  
        Map temp =  null;  
        Map> resMap =new HashMap>();  
        try {  
                //取得皮膚包中的R文件  
                Class rClass = skinContext.getClassLoader().loadClass(packageName+".R");  
                //取得記錄各種資源的ID的類  
                Class[] resClass =rClass.getClasses();  
                String className,resourceName;  
                int resourceId=0;  
                for(int i=0;i();  
                            temp.put(resourceName, resourceId);  
                            Log.i("DDDDD", "className:"+className+"  resourceName:"+resourceName+"  " +  
                                    "resourceId:"+Integer.toHexString(resourceId));  
                        }  
                    }  
                    //由於內部類的關系className應該是com.skin.R$layout的形式  
                    //截掉前面的包名和.R$以方便使用  
                    className = className.substring(packageName.length()+3);  
                    resMap.put(className, temp);  
                }  
            } catch (ClassNotFoundException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        return resMap;  
        } 

最後通過資源ID和skinContext可以訪問到指定包下的所有資源,例如要訪問layout
/** 
     * 獲取皮膚包中的layout 
     * 並轉化為VIEW 
     * @param layoutName 
     * @return 
     */  
    private View getLayoutFromSkin(String layoutName)  
    {  
        View view;  
        if(resMap == null)  
            return null;  
        Map temp = resMap.get("layout");  
        int viewId = (Integer) temp.get(layoutName);  
        if(viewId != 0)  
        {  
            //引用皮膚包資源轉化View  
            LayoutInflater inflater =LayoutInflater.from(skinContext);  
            view = inflater.inflate(skinContext.getResources().getLayout(viewId), null);  
        }  
        else  
        {  
            view = null;  
        }  
        return view;  
    }  

注:換皮膚思路詳見:http://blog.csdn.net/tangnengwu/article/details/22801107


2. 訪問android 隱藏的API

Toast信息框的關閉是由系統管理的,因為hide方法是隱藏的開發者沒有辦法直接調用,這種情況下可以用發射機制獲取這個方法,創建一個顯示和隱藏都由開發者控制的Toast信息框。

package com.example.reflection;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MyToast 
{
	Context context=null;
	Object obj =null;
	public MyToast(Context context,String text)
	{
		this.context =context;
		Toast toast =Toast.makeText(context, text, 1);
		try {
			Field field = toast.getClass().getDeclaredField("mTN");
			field.setAccessible(true);
			obj =field.get(toast);
		} catch (Exception e) {
			// TODO: handle exception
			Log.d("AAA", "MyToast Exception--->"+e.toString());
		}
	}
	public void show()
	{           
		try {
			//android4.0以上就要以下處理
//			Field mNextViewField = obj.getClass().getDeclaredField("mNextView");
//	        mNextViewField.setAccessible(true);
//			LayoutInflater inflate = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//          View v = inflate.inflate(R.layout.ui_toast, null);			
//	        mNextViewField.set(obj, v);
			Method method =obj.getClass().getDeclaredMethod("show", null);
			method.invoke(obj, null);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			Log.d("AAA", "show Exception--->"+e.toString());
			e.printStackTrace();
		}
	}
	public void hide()
	{
		try {
			Method method =obj.getClass().getDeclaredMethod("hide", null);
			method.invoke(obj, null);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			Log.d("AAA", "hide Exception--->"+e.toString());
			e.printStackTrace();
		}
	}

}

顯示toast:
MyToast toast = new MyToast(this, "反射機制!");
toast.show();
隱藏toast:

toast.hide();

注意在4.0以上的版本中,還需要對Toast 中的View進行處理,如代碼中所示


3. 修改某些“不可改” 的系統資源

ListView組件沒有提供修改快速滑塊圖像的API,因此不能直接修改,但可通過反射實現

package com.example.reflection;

import java.lang.reflect.Field;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.AbsListView;
import android.widget.ListView;

public class MListView extends ListView 
{
	public MListView(Context context, AttributeSet attrs) 
	{
		super(context, attrs);
		// TODO Auto-generated constructor stub
		setNewDrawable(context);
	}
	
	private void setNewDrawable(Context context)
	{
		try {
			Field  field = AbsListView.class.getDeclaredField("mFastScroller");
			field.setAccessible(true);
			Object obj = field.get(this);
			field =field.getType().getDeclaredField("mThumbDrawable");		
			field.setAccessible(true);
			Drawable drawable = (Drawable)field.get(obj);
			drawable = context.getResources().getDrawable(R.drawable.ic_launcher);
			field.set(obj, drawable);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
Field  field = AbsListView.class.getDeclaredField("mFastScroller");
FastScroller.mThunbDrawable變量保存了快速滑塊圖像,但首先要獲取AbsListView.mFastScroller變量



    


android:fastScrollEnabled="true"
使用快速滑塊

效果圖如下:

\


總結:

Java中的反射機制,被稱為Reflection,它允許運行中的Java程序對自身進行檢查,並能直接操作程序的內部屬性或方法。Reflection機制允許程序在正在執行的過程中,利用Reflection APIs取得任何已知名稱的類的內部信息,包括:package、 type parameters、 superclass、 implemented interfaces、 inner classes、 outer classes、 fields、 constructZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcnOhoiBtZXRob2RzoaIKIG1vZGlmaWVyc7XIo6yyor/J0tTU2ta00NC1xLn9s8zW0KOstq/MrMn6s8lJbnN0YW5jZXOhorHkuPxmaWVsZHPE2sjdu/K7vcbwbWV0aG9kc6Gj1Nm0zrv5tKHJz87Sw8e/ydLUwPvTw7e0yeS7+tbG1NpKYXZhs8zQ8tbQo6y2r8ystcTIpbX308PSu9CpcHJvdGVjdGVkyfXWwcrHcHJpdmF0ZbXEt723qLvywOCjrNXi0fm/ydLUuty087PMtsjJz8L61+PO0sPHtcTSu9Cpsci9z8zYyuLQ6MfzoaM8YnI+CjwvcD4KPHA+PGJyPgo8L3A+CjxwPtPQudi3tMnkvLzK9bXEQVBJOjwvcD4KPHA+Q2xhc3PA4KO6PC9wPgogIENsYXNzwOC0+rHt18XEs7j2wOC1xNfWvdrC66Os0qrKudPDt7TJ5KOsvs3Q6NKqyKG1w7bU06a1xENsYXNzttTP86OsyLu6877Nzai5/dXiuPa21M/zo6y+zb/JveLGyrP2wOC1xLPJ1LGx5MG/o6yzydSxt723qLXItcihozxicj4KICC78cihQ2xhc3PA4LbUz/M8YnI+Ci8vzai5/UNsYXNztcRmb3JOYW1lKCm3vbeoLLTLt723qNfuzqqzo9PDICAKQ2xhc3MgY2xhc3MxID0gQ2xhc3MuZm9yTmFtZShjbGFzc05hbWUpOyAgCi8vzai5/SAuY2xhc3MgIApDbGFzcyBjbGFzczIgPSBYWFguY2xhc3M7ICAKLy/NqLn9ttTP87vxtcMgIApDbGFzcyBjbGFzczMgPSBuZXcgWFhYKCkuZ2V0Q2xhc3MoKTsgIDxicj4KCjxicj4KCiAgQ2xhc3PA4LXEs6PTw7e9t6ijujxicj4KCiAgZ2V0Q29uc3RydWN0b3IoKSC78cihubnU7Lqvyv0KICBnZXRNZXRob2QoKSAgu/HIobPJ1LG3vbeoCiAgZ2V0RmllbGQoKSC78cihs8nUsbHkwb8KICBnZXREZWNsYXJlZENvbnN0cnVjdG9yKCkgu/HIocu909C1xLm51Oy6r8r9CiAgZ2V0RGVjbGFyZWRNZXRob2QoKSAgu/HIocu909C1xLPJ1LG3vbeoCiAgZ2V0RGVjbGFyZWRGaWVsZCgpILvxyKHLvdPQtcSzydSxseTBvwo8cD7IobXDbWV0aG9kttTP89auuvM8L3A+CjxwPrX308M8L3A+CjxwcmUgY2xhc3M9"brush:java;">method.invoke(obj, null)使用該方法

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved