讓我們一起來擺脫findviewbyid吧!!!


這個題目,可能或多有一些的誇張,實際上是這樣的。也不能說是擺脫吧,最終還是要使用findviewbyid的!!

事情是這樣的,大家在普通開發的時候,是不是經常的遇到這樣的一個問題.Android開發的過程中,其實極大的使用了Mvc的這種設計模式,我也是最近深有感觸。

一般的應用:如果按照我的思維,我會將其大體的分為三類,model,view.xml,與view.java,model不用說,肯定是模型類,view.xml就是布局文件,而view.java則是

用於將數據綁定給xml的一個控制類吧,哈哈,說得可能不標准。大家在開發的過程中,是不是深有感觸,就是在執行第三步的時候,使用view.java,將傳入的數據綁定到view.xml

界面元素中,大量的使用findviewbyid,來對各個組件進行實例化,這點是不是特煩人?對,很煩人的,如果說界面的元素稍微的少一些,還行,寫得還挺代感 的,如果說界面的元素多了的話,那是有點痛苦了。

后面我就想,能不能讓應用自動的 為我們生成這一些代碼,也就是實例化控件的代碼?

1)首先想到的就是反射,再通過遞歸的方式,將界面的所有元素全部例舉出來,根據相應控件進行代碼的拼接。當然,其實,在在遍歷的過程中,完全可以實例化,創建相應的組件,考慮到運行時如果是這種方法的話,程序的運行效率會很低。后面和一位朋友討論了一下,采用了代碼拼接的方式。接下來就一起來看看怎么一步一步實現的。

如以下的是view.xml的布局文件

 

 代碼如下 :(博客園上面的代碼上傳實在是不好使)

 <?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:id="@+id/container">
    <EditText
        android:id="@+id/user_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" 
        android:text="DoGet">
        <requestFocus />
    </EditText>
    <EditText
        android:id="@+id/pass_word"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" 
        android:text="DoGet123"/>
    <Button
        android:id="@+id/login_nopass"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ButtonLogin" />
    <Button
        android:id="@+id/login_web"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="web" />
    <Button
        android:id="@+id/login_wap"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="wap" />
    <TextView
        android:id="@+id/result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView" />
</LinearLayout>

 

activity前台使用類:

 

 package com.doget.froeachview;//http://ssyinxx.blog.163.com/blog/static/187302318201282033017883/

import java.lang.reflect.Field;
import java.util.HashMap;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.doget.updateapk.UpdateManager;
import com.doget.xmpp_demo.R;
public class Foreach_Act extends Activity {
LinearLayout linear;
String temp = "";
UpdateManager manager;
HashMap<String, String> maps = new HashMap<String, String>();
public Foreach_Act() {
// TODO Auto-generated constructor stub
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.wifi_demo);
// 找到最外層的容器
ViewGroup v = (ViewGroup) findViewById(R.id.container);
// 找到R.id類,得到其所有的屬性以極相應的值
Field[] fields = R.id.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
try {
// Log.i("field",
// "fieldinfo     field_name"+fields[i].getName()+"   field_value:"+fields[i].get(R.id.class).toString());
maps.put(fields[i].get(R.id.class).toString(),
fields[i].getName());
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
findChildView(v);
Log.i("finalCode", temp);
Toast.makeText(this, "執行", 1000).show();
// 自動更新測試
Log.i("finalCode", "開始更新22222");
manager = new UpdateManager(this);
manager.checkUpdate();
Log.i("finalCode", "開始更新33333");
}
public void findChildView(ViewGroup v) {
for (int i = 0; i < v.getChildCount(); i++) {
View obj = v.getChildAt(i);
// 這下邊暫時就先例舉出來以如下這一些,當然還有其它的一些類型
if (obj instanceof Button) {
// 判斷是否在R文件中有定義,如果有定義,則為其創建代碼
if (maps.get(String.valueOf(obj.getId())) != null) {
temp += createCode(obj.getClass().getSimpleName(),
maps.get(String.valueOf(obj.getId())));
}
} else if (obj instanceof TextView) {
if (maps.get(String.valueOf(obj.getId())) != null) {
temp += createCode(obj.getClass().getSimpleName(),
maps.get(String.valueOf(obj.getId())));
}
}
if (obj instanceof LinearLayout) {
LinearLayout linear = (LinearLayout) obj;
// Log.i("findview", "linear-----id:"+obj.getId()
// +"   classname-->"+obj.getClass().getSimpleName());
findChildView(linear);
}
if (obj instanceof RelativeLayout) {
RelativeLayout rela = (RelativeLayout) obj;
// Log.i("findview", "linear-----id:"+obj.getId()
// +"   classname-->"+obj.getClass().getSimpleName());
findChildView(rela);
}
}
}
// (類型) 名稱=(類型)findViewById(數值);
// (類型) ddd=(類型)findViewById(數字);
public String createCode(String type, String name) {
// 這個地方,可以根據大家要求進行更改
String code = type + "  " + name + "  =(" + type
+ ")findViewById(R.id." + name + ");";
return code + "\n";
}
}

 快來看看,竟然生成了:

 

 

 

形式,有多種,大家可以根據自己的需要進行更改。同時,需要注意的一下是,要使用這個方法,得有一個初始的尋找起點,就是視圖最外層的那個容器必須得有一個id,不然,就不會再往下找了。通過這種方式,把生成的代碼,往自己的代碼里面一放,是不是快多了。但是,這好像第三方調用起來是乎還有一些的麻煩。還是封裝一下吧。 

 package com.doget.froeachview;

import java.lang.reflect.Field;
import java.util.HashMap;
import com.doget.xmpp_demo.R;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class sffindview {
View mView=null;
String temp = "";
String viewname="";
HashMap<String, String> maps = new HashMap<String, String>();
/**
* 參數:上下文,R.id類文件,需要查找 的視圖,查找 的起點id,視圖名稱
*/
public sffindview(Context context,Class r_id,int resourceid,int originid,String viewname) {
// TODO Auto-generated constructor stub
mView=LayoutInflater.from(context).inflate(resourceid, null);
// 找到最外層的容器
ViewGroup v = (ViewGroup) mView.findViewById(R.id.container);
// 找到R.id類,得到其所有的屬性以極相應的值
Field[] fields = r_id.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
try {
// Log.i("field",
// "fieldinfo     field_name"+fields[i].getName()+"   field_value:"+fields[i].get(R.id.class).toString());
maps.put(fields[i].get(R.id.class).toString(),
fields[i].getName());
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.viewname=viewname;
   Log.i("net", "代碼開始生成.......................................................................");
findChildView(v);
Log.i("net", temp);
   Log.i("net", "代碼生成完畢.......................................................................");
}
public void findChildView(ViewGroup v) {
for (int i = 0; i < v.getChildCount(); i++) {
View obj = v.getChildAt(i);
// 這下邊暫時就先例舉出來以如下這一些,當然還有其它的一些類型
if (obj instanceof Button) {
// 判斷是否在R文件中有定義,如果有定義,則為其創建代碼
if (maps.get(String.valueOf(obj.getId())) != null) {
temp += createCode(obj.getClass().getSimpleName(),
maps.get(String.valueOf(obj.getId())));
}
} else if (obj instanceof TextView) {
if (maps.get(String.valueOf(obj.getId())) != null) {
temp += createCode(obj.getClass().getSimpleName(),
maps.get(String.valueOf(obj.getId())));
}
}
if (obj instanceof LinearLayout) {
LinearLayout linear = (LinearLayout) obj;
// Log.i("findview", "linear-----id:"+obj.getId()
// +"   classname-->"+obj.getClass().getSimpleName());
findChildView(linear);
}
if (obj instanceof RelativeLayout) {
RelativeLayout rela = (RelativeLayout) obj;
// Log.i("findview", "linear-----id:"+obj.getId()
// +"   classname-->"+obj.getClass().getSimpleName());
findChildView(rela);
}
}
}
// (類型) 名稱=(類型)findViewById(數值);
// (類型) ddd=(類型)findViewById(數字);
public String createCode(String type, String name) {
// 這個地方,可以根據大家要求進行更改
String code="";
if(viewname==null||viewname.equals(""))
{
code = type + "  " + name + "  =(" + type
+ ")"+viewname+"findViewById(R.id." + name + ");";
}
else
{
   code = type + "  " + name + "  =(" + type
+ ")"+viewname+".findViewById(R.id." + name + ");";
}
return code + "\n";
}
}

 使用代碼: sffindview sf=new sffindview(this, R.id.class, R.layout.wifi_demo, R.id.container, "sf");

 

執行結果: 

 

 

 

 

 

 歡迎大家擴展!!!!好了,今天講到 這里!!!

 

 

 

 

 

 

 

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com