zoukankan      html  css  js  c++  java
  • 让我们一起来摆脱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 + " ";
    }
    }

     快来看看,竟然生成了:

     

    形式,有多种,大家可以根据自己的需要进行更改。同时,需要注意的一下是,要使用这个方法,得有一个初始的寻找起点,就是视图最外层的那个容器必须得有一个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 + " ";
    }
    }

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

    执行结果: 

     

     欢迎大家扩展!!!!好了,今天讲到 这里!!!

     

  • 相关阅读:
    vue---echarts图表
    路由嵌套
    VoIP语音通话研究【进阶篇(四):freeswitch+webrtc+sip.js的通话】
    VoIP语音通话研究【进阶篇(三):opensips安装】
    如何在北京退休?
    后端分析/前端分析/边缘分析
    使用curl批量下载图片
    pytorch固定随机种子复现实验结果
    分享一个作为面试官的面试思路
    两个流程链路问题的排查和总结
  • 原文地址:https://www.cnblogs.com/wsfjlagr/p/3460280.html
Copyright © 2011-2022 走看看