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();  

  } 

本人初出茅庐,文中难免有错误之处,还望指正,谢谢!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值