【攻克Android (34)】Butter Knife 黄油刀

[b][size=large]本文围绕以下四个部分展开:[/size][/b]

[b][size=large]一、注解式框架[/size][/b]
[b][size=large]二、Butter Knife[/size][/b]
[b][size=large]案例一[/size][/b]
[b][size=large]案例二:用 ListView 展示一个列表数据,每个Item里含有一个Button,可以点击。[/size][/b]


[b][size=large]一、注解式框架[/size][/b]

[size=medium][b]1. 注解式开发:[/b][/size]

[size=medium]JDK 1.5后支持注解方式。想用注解式开发,就要自定义注解。[/size]

[size=medium]@Override就是一种自带的注解。很多框架都采用注解方式来实现。[/size]

[size=medium]当追求更高的开发效率,用更简洁的代码、更清晰的代码逻辑来进行高效的开发的时候,使用注解式框架开发可[b]简化代码[/b],[b]提升开发效率[/b]和[b]代码的可读性[/b]。 [/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9702/d77fbac9-cc18-341e-ae2e-751d246590e5.png[/img][/align]

[size=medium][b]2. 主流注解式框架:[/b][/size]

[size=medium](1)AndroidAnnotations[/size]

[size=medium]配置麻烦,需要在功能清单文件中注册生成的子类。反射机制会占用资源内存,且耗时。[/size]

[size=medium](2)Dagger[/size]

[size=medium]采用预编译技术,高效。但是对View绑定操作注解不是很方便。[/size]

[size=medium](3)Butter Knife[/size]

[size=medium]它是View 及事件等依赖注入框架。使用方便,配置简单,有强大的View注入绑定和简单的常用方法注解。[/size]


[b][size=large]二、Butter Knife[/size][/b]

[size=medium]它是View 及事件等依赖注入框架。[/size]

[size=medium][b]1. 特点:[/b][/size]

[size=medium](1)强大的View注入绑定和Click事件的处理。简化代码,提升开发效率。[/size]

[size=medium](2)可以方便地处理ListView的Adapter里的ViewHolder绑定问题。[/size]

[size=medium](3)运行时不会影响App效率,使用配置方便。[/size]

[size=medium](4)代码思路清晰,可读性强。[/size]

[size=medium][b]2. 用法:[/b][/size]

[size=medium][b]导包:[/b][/size]

[size=medium][color=red]compile 'com.jakewharton:butterknife:6.0.0'[/color][/size]

[size=medium][b]在当前 Activity(this)的onCreate中注册(注入黄油刀):[/b][/size]

ButterKnife.inject(this);


[size=medium](1)View绑定(绑定控件):[/size]

[size=medium]Activity声明绑定控件:[/size]

    @InjectView(R.id.tvTitle) 
TextView tvTitle;


[size=medium]黄油刀注入控件,相当于:先声明变量,然后通过 findViewById(R.id.tvCompany) 初始化变量。黄油刀直接帮我们绑定好了控件:[/size]

[size=medium]InjectView: Bind a field to the view for the specified ID. The view will automatically be cast to the field type.[/size]

    @InjectView(R.id.tvTitle) // 相当于 通过 findViewById(R.id.tvCompany) 初始化变量。
TextView tvTitle; // 相当于 声明变量:private TextView tvCompany;


[size=medium]注意:不同写为:private TextView tvTitle; 会报错:@InjectView fields must not be private or static.[/size]

[size=medium](2)Onclick等事件处理:[/size]

    @OnClick(R.id.btnHello)
public void sayHi(){
Toast.makeText(this,"你好!",Toast.LENGTH_SHORT).show();
}


[size=medium](3)ListView的Adapter里的ViewHolder绑定问题。[/size]


[b][size=large]案例一[/size][/b]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9683/15a1e9ca-b3fb-3ab9-917f-5d50e9a4eff8.png[/img][/align]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9685/a270b60f-4efe-3f55-b09c-0969fa59194d.png[/img][/align]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9687/1724a6dd-7e43-3713-82ea-d6543350018e.png[/img][/align]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9689/31898c2e-cb6e-3142-a169-56e7b81df2e1.png[/img][/align]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9691/e979a6d6-b7c5-3eb3-b2c2-e3c02f7b9312.png[/img][/align]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9696/e24eeff8-7604-31f0-a2ea-adecaedd128b.png[/img][/align]


[size=medium][b]1. strings.xml。字符串。[/b][/size]

<resources>
<string name="app_name">ButterKnifeDemo</string>

<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>

<string name="btn_good_night">Good Night!</string>
<string name="btn_play">播放</string>
<string name="btn_stop">停止</string>
<string name="btn_view_holder">ViewHolder</string>
</resources>


[size=medium][b]2. activity_main.xml。布局[/b][/size]

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">

<Button
android:id="@+id/btnHello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"/>

<Button
android:id="@+id/btnGoodNight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btnHello"
android:text="@string/btn_good_night"/>

<Button
android:id="@+id/btnPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btnGoodNight"
android:text="@string/btn_play"/>

<Button
android:id="@+id/btnStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btnPlay"
android:text="@string/btn_stop"/>

<Button
android:id="@+id/btnViewHolder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btnStop"
android:text="@string/btn_view_holder"/>

</RelativeLayout>


[size=medium][b]3. MainActivity。View绑定和Onclick事件处理[/b][/size]

package com.android.butterknifedemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnClick;
import butterknife.Optional;


public class MainActivity extends Activity {

// 2. Actitvity里声明绑定控件
// @Optional:加入后,若此id不存在,则程序不会崩溃,而是抛出异常
@Optional@InjectView(R.id.btnHello)
Button buttonHello;
@InjectView(R.id.btnPlay)
Button buttonPlay;
@InjectView(R.id.btnStop)
Button buttonStop;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// 1. onCreate() 方法里注册 ButterKnife
ButterKnife.inject(this);
}

// 3. 注入 View 事件,不带参数
@OnClick(R.id.btnHello)
public void sayHi(){
Toast.makeText(this,"你好!",Toast.LENGTH_SHORT).show();
}

// 4. 注入 View 事件,带参数
@OnClick(R.id.btnGoodNight)
public void sayGoodNight(Button btnGoodNight){
btnGoodNight.setText("晚上好!");
}

// 5. 同时注入多个 View 事件
@OnClick({R.id.btnPlay,R.id.btnStop})
public void playMusic(View view){
switch (view.getId()){
case R.id.btnPlay:
Toast.makeText(this,"播放音乐",Toast.LENGTH_SHORT).show();
break;
case R.id.btnStop:
Toast.makeText(this,"停止播放",Toast.LENGTH_SHORT).show();
}
}


// ----------------------------------------------------------
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}
}


[size=medium][b]4. MyAdapter。处理ListView的Adapter里的ViewHolder绑定问题。[/b][/size]

package com.android.butterknifedemo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;

import butterknife.ButterKnife;
import butterknife.InjectView;

/**
* 在 ViewHolder 模式中注入
*/
// 1. 继承自 BaseAdapter
public class MyAdapter extends BaseAdapter{
// 4. 定义上下文
private Context mContext;

/**
* 5. 构造方法
* @param context
*/
public MyAdapter(Context context) {
// 上下文通过构造方法传过来
mContext = context;
}

@Override
public int getCount() {
return 0;
}

@Override
public Object getItem(int position) {
return position;
}

@Override
public long getItemId(int position) {
return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 3. 声明 holder 为空
ViewHolder holder = null;

// 6.
if(holder==null){
// 重新载入布局
convertView = LayoutInflater.from(mContext).inflate(
R.layout.activity_main,parent,false);
// 对 holder 进行实例化
holder = new ViewHolder(convertView);
// 获得按钮控件
holder.btnViewHolder = (Button) convertView.findViewById(R.id.btnViewHolder);
// 设置标签
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// 7.
holder.btnViewHolder.setText("更改");
return convertView;
}

// 2. 写一个 结构持有者 类
static class ViewHolder{
@InjectView(R.id.btnViewHolder)
Button btnViewHolder;

public ViewHolder(View view){
ButterKnife.inject(this,view);
}
}
}



[b][size=large]案例二:用 ListView 展示一个列表数据,每个Item里含有一个Button,可以点击。[/size][/b]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9919/87b2c727-71d4-3372-a84d-6acbe6876830.png[/img][/align]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9921/e3bcf193-c47c-311c-ab7d-d92a35e749f7.png[/img][/align]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9923/453bbac4-1ba2-3e4f-b0d2-3ebfa4243935.png[/img][/align]

[align=center][img]http://dl2.iteye.com/upload/attachment/0110/9925/923342a3-ac18-37d9-904e-0513fb9b6dcc.png[/img][/align]


[size=medium][b]1. activity_main.xml。布局:一个ListView。[/b][/size]

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">

<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</RelativeLayout>


[size=medium][b]2. item.xml。每一个ListView的项。包括一个文本和一个按钮[/b][/size]

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">

<TextView
android:id="@+id/tvText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name" />

<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/tvText" />

</RelativeLayout>


[size=medium]注:ListView中出现button等可以拦截点击事件的控件的时候,要加属性:[/size]

android:descendantFocusability="blocksDesendants"


[size=medium][b]3. MyAdapter。自定义适配器。[/b][/size]

package com.android.bufferknifedemo;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

import butterknife.ButterKnife;
import butterknife.InjectView;

/**
* Created by Xiangdong on 2015/7/12.
*/
public class MyAdapter extends BaseAdapter {
Context mContext;
private ArrayList<String> lists;

public MyAdapter(Context context, ArrayList<String> list) {
mContext = context;
lists = list;
}

@Override
public int getCount() {
return lists.size();
}

@Override
public Object getItem(int position) {
return lists.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = View.inflate(mContext, R.layout.item, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}

String s = lists.get(position);
holder.tvText.setText(s);
holder.btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, "点击", Toast.LENGTH_SHORT).show();
}
});
return convertView;
}

static class ViewHolder {
// 绑定控件
@InjectView(R.id.tvText)
TextView tvText;
@InjectView(R.id.btn)
Button btn;

public ViewHolder(View view) {
ButterKnife.inject(this, view);
}
}
}


[size=medium][b]4. MainActivity。[/b][/size]

package com.android.bufferknifedemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;

import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnItemClick;

public class MainActivity extends Activity {
@InjectView(R.id.listView)
ListView listView;
private MyAdapter adapter;
private ArrayList<String> list;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ButterKnife.inject(this);

list = new ArrayList<>();
list.add("测试1");
list.add("测试2");
list.add("测试3");
list.add("测试4");
list.add("测试5");
list.add("测试6");
list.add("测试7");
list.add("测试8");
list.add("测试9");
adapter = new MyAdapter(this, list);
listView.setAdapter(adapter);
}

@OnItemClick(R.id.listView)
public void onMyItemClick(int position) {
Toast.makeText(this, "位置:" + position, Toast.LENGTH_SHORT).show();
}

// ------------------------------------------------------------------
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}
}



[b][size=large][color=red]整理时重点参考:[/color][url]http://www.jikexueyuan.com/course/1320.html[/url][/size][/b]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值