Android中广播的遵循的原则,README.md

# Wei.Lib2A

------------------------------------------------------------------------------------------------

---

2016年新增内容:

### 全新基于`@Annotation`的混淆配置库

* 已独立迁移至github并上传jcenter: [Annoguard](http://github.com/WeiChou/Annoguard)

------------------------------------------------------------------------------------------------

---

Android快速开发库,Android常用工具集。任务管理、数据加载、下载库请查阅其他项目。

对于初学者欢迎加 [QQ群:215621863](http://shang.qq.com/wpa/qunwpa?idkey=c39a32d6e9036209430732ff38f23729675bf1fac1d3e9faac09ed2165ae6e17 "Android编程&移动互联") 相互学习探讨!

### 这个库都有什么?能帮我们做什么?

#### 我写代码遵循两个基本原则:

* 减少代码量。希望达到的效果是,让使用者尽可能减少代码,能一句话搞定的,绝不两句,能静态方法搞定的,绝不new对象;

* 增强适应性和稳定性。由于Android平台厂商定制的碎片化和众多版本兼容性问题,本库的开发会着重考虑这些因素,而且基本都是经上线的项目考验过的。

本库的所有代码都经过本人严格测试,字斟句酌,了如指掌,注释也很清晰。覆盖Android基础开发的方方面面,推荐作为项目的基础框架来使用,以便于各功能的正常便利集成。有任何疑问或建议请联系作者:

[weichou2010@gmail.com](mailto:weichou2010@gmail.com)、[微信](http://github.com/WeiChou/Wei.Lib2A/#联系作者) 或 [加群@群主](http://shang.qq.com/wpa/qunwpa?idkey=c39a32d6e9036209430732ff38f23729675bf1fac1d3e9faac09ed2165ae6e17 "Android编程&移动互联")。

### 基础常用组件介绍如下:

### 1、存储卡工具类 [Storage](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/phone/Storage.java)

仅通过几个常量即可便捷的取得内置或外置存储卡 [Storage.SdCard](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/phone/Storage.java#L149) 对象。例如:

```Java

//输出外置存储卡的路径到logcat

if (Storage.CARD_EXT != null) L.i(this, Storage.CARD_EXT.path);

//是否可以在默认的卡上创建任意目录

if (Storage.CARD_DEF.isCustomDirCreatable(context)) {

//...

try {

File dir = FileUtils.makeDir(dirPath, true);

L.i(this, dir.getPath());

//...

} catch (FileCreateFailureException e) {

L.e(this, e);

}

}

```

### 2、存储卡自动选择与存储 [FStoreLoc](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/file/FStoreLoc.java)

仅有`存储卡工具`就够了吗?它需要去判断存储卡是否存在、能否创建目录和文件,再决定是否写文件。而`FStoreLoc`可以一步完成:

```Java

public static File getImagesCacheDir() throws SdCardNotMountedException,

SdCardNotValidException, FileCreateFailureException {

return FStoreLoc.BIGFILE.getImagesCacheDir(get(), DirLevel.CUSTOM);

}

```

* 上面代码中的 [`DirLevel.CUSTOM`](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/file/FStoreLoc.java#L65)

表示选择自定义根目录,只有在存储卡支持创建自定义目录时才有效,否则抛异常。当然也可选择私有目录

[`DirLevel.PRIVATE`](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/file/FStoreLoc.java#L67)

或自适应目录 [`DirLevel.DEFAULT`](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/file/FStoreLoc.java#L69),详见代码中的文档。

`FStoreLoc`有三种预置存储模式:

* 小文件模式:[`FStoreLoc.DEFAULT`](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/file/FStoreLoc.java#L50);

* 大文件模式:[`FStoreLoc.BIGFILE`](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/file/FStoreLoc.java#L52);

* 生存模式:[`FStoreLoc.SURVIVE`](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/file/FStoreLoc.java#L60).

而`大文件模式`和`生存模式`根据业务需要可能需要设置存储卡根目录,那就放在App初始化里:

```Java

public class App extends AbsApp {

@Override

public void onCreate() {

Debug.DEBUG = isDebugMode();

if (Debug.DEBUG) {

//...

}

super.onCreate();

//...

/* 设置大文件模式的文件根目录。若存储卡根目录允许写文件,则创建该目录,否则会使用存储卡上的

* 系统为App分配的私有目录:Android/appname/files/

* 大文件模式,即只存放在内置或外置存储卡上,外置优先。

*/

FStoreLoc.BIGFILE.setBaseDirName(this, Const.APP_DIR_NAME);

//切换到外置卡(默认会自动选择剩余空间最大的那张卡)。但是读写文件过程中如果不存在会自动切换到内置卡。

FStoreLoc.BIGFILE.switchTo(this, Storage.CARD_EXT);

}

//...

}

```

### 3、文件工具 [FileUtils](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/file/FileUtils.java) 和基于版本控制的多进程文件并发读写工具 [FileVersioned](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/file/FileVersioned.java)

### 4、增强的SharedPreferences工具:[Keeper](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/persist/Keeper.java)

具有多进程读写安全、基于Locale的文件隔离能力等。

基本用法:

```Java

public final class XxxKeeper extends Keeper.Wrapper {

private static final String SPREF_NAME = "spref_name";

// 以下为固定写法

public static WrapperImpl get() {

return get(AbsApp.get().getApplicationContext(), SPREF_NAME);

}

public static final String KEY_VIEW_PEGER_INDEX = "view_peger_index";

private static final String KEY_XXX_JSON = "xxx_json";

// ...

public static void saveXxxObj(XxxObj entity) {

get()

.withLocale() // 根据需求可选

.multiProcess() // 根据需求可选

.edit() // 根据需求可选

.keepString(KEY_XXX_JSON, AbsJson.toJsonWithAllFields(entity));

// 如果上面的Api无法满足需求,可用原生的

.getSharedPreferences()

.putString(KEY_XXX_JSON, AbsJson.toJsonWithAllFields(entity))

.xxx();

}

public static XxxObj getXxxObj() {

try {

return AbsJson.fromJsonWithAllFields(

get()

.withLocale() // 根据需求可选

.multiProcess() // 根据需求可选

.edit() // 根据需求可选

.readString(KEY_XXX_JSON)

// 如果上面的Api无法满足需求,可用原生的

.getSharedPreferences()

.getString(KEY_XXX_JSON, null)

, XxxObj.clazz);

} catch (Exception e) {

return null;

}

}

}

// 或者这样使用

XxxKeeper.get().

.withLocale() // 根据需求可选

.multiProcess() // 根据需求可选

.edit() // 根据需求可选

.keepInt(XxxKeeper.KEY_VIEW_PEGER_INDEX, 1);

// 如果上面的Api无法满足需求,可用原生的

.getSharedPreferences()

.putInt(XxxKeeper.KEY_VIEW_PEGER_INDEX, 1)

.xxx();

```

### 5、网络连接状况判断 [Network](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/phone/Network.java)

### 6、网络连接状况监听 [NetConnectionReceiver](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/receiver/net)

### 7、存储卡挂载状况监听 [StorageReceiver](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/receiver/storage)

示例:

```Java

@Override

protected void onResume() {

super.onResume();

NetConnectionReceiver.registerObserver(mNetObserver);

StorageReceiver.registerObserver(mToastStorageObserver);

//StorageReceiver.registerObserver(mStorageObserver);

}

@Override

protected void onPause() {

StorageReceiver.unregisterObserver(mToastStorageObserver);

//StorageReceiver.unregisterObserver(mStorageObserver);

NetConnectionReceiver.unregisterObserver(mNetObserver);

super.onPause();

}

private final NetObserver mNetObserver = new NetObserver() {

@Override

public void onChanged(Type type, State state) {

ensureViewState(true, false);

}

};

private final ToastStorageObserver mToastStorageObserver = new ToastStorageObserver(this);

private final StorageObserver mStorageObserver = new StorageObserver() {

/**按下"MediaButton"按键时发出的广播,假如有"MediaButton"按键的话(硬件按键),

* Intent.EXTRA_KEY_EVENT携带了这个KeyEvent对象**/

protected void onMediaButton(KeyEvent ev) {}

/**已经插入,但是不能挂载**/

protected void onMediaUnMountable(SdCard sdcard) {}

/**对象为空白或正在使用不受支持的文件系统,未格式化**/

protected void onMediaNoFS(SdCard sdcard) {}

/**扩展介质被插入,而且已经被挂载。intent包含一个名为"read-only"的boolean extra表明挂载点是否只读**/

protected void onMediaMounted(SdCard sdcard, boolean readOnly) {}

/**正在磁盘检查**/

protected void onMediaChecking(SdCard sdcard) {}

/**请求媒体扫描器扫描存储介质,以将媒体文件信息放入数据库**/

protected void onMediaScannerScanFile(String filePath) {}

/**媒体扫描器开始扫描文件目录**/

protected void onMediaScannerStarted(String dirPath) {}

/**媒体扫描器完成扫描文件目录**/

protected void onMediaScannerFinished(String dirPath) {}

/**由于通过USB存储共享导致无法挂载,挂载点路径可参见参数Intent.mData**/

protected void onMediaShared(SdCard sdcard) {}

/**用户希望弹出外部存储介质,收到此广播之后应该立即关闭正在读写的文件;

* 要弹出的卡的路径在intent.getData()里面包含了,可以先判断是不是正在读写的文件的那个卡**/

protected void onMediaEject(SdCard sdcard) {}

/**已经卸载但未拔出**/

protected void onMediaUnmounted(SdCard sdcard) {}

/**已经卸载并拔出**/

protected void onMediaRemoved(SdCard sdcard) {}

/**未卸载直接拔出**/

protected void onMediaBadRemoval(SdCard sdcard) {}

}

```

### 8、托管广播事件监听器 [EventDelegater](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/framework/EventDelegater.java)

基于但简化了`Broadcast`和`LocalBroadcast`的发送/接收操作,在页面初始化的时候可以调用[AbsActivity/AbsFragment.hostingLocalEventReceiver(...)](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/framework/AbsActivity.java#L233)将事件监听器进行托管,不再需要在`onPause()`、`onResume()`以及`onDestroy()`等事件的时候进行`unregisterXxx()`和`registerXxx()`编码,托管组件将自动完成。受惠于`Broadcast`的松散耦合机制和简化了的发送/接收操作,可将传统的`Callack`模式用本事件模式重构,轻松解决由于某些原因导致的`资源无法释放`和`内存泄露`等问题。示例:

```Java

//在Activity或Fragment中发送事件

@ViewLayoutId(R.layout.m_f_tabs_left_btn_page)

public class MTabsLeftFrgmt extends AbsFragment {

public void scroll2TopAndRefresh() {

//发送事件

sendLocalEvent(mRbtnRecommend.isChecked() ? Const.EventName.SCROLL_2_TOP_AND_REFRESH_frgmt_recommend

: Const.EventName.SCROLL_2_TOP_AND_REFRESH_frgmt_favorite, null);

}

//...

}

//在子Fragment中接收事件

@ViewLayoutId(R.layout.f_m_f_tabs_left_btn_page_recommend)

public class RecommendFrgmt extends AbsFragment {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//只需要提前托管就好了,不用考虑onPause()、onResume()以及onDestroy()的时候还要取消注册或重新注册事件监听

hostingLocalEventReceiver(Const.EventName.SCROLL_2_TOP_AND_REFRESH_frgmt_recommend, PeriodMode.PAUSE_RESUME, new EventReceiver() {

@Override

public void onEvent(Bundle data) {

scroll2TopAndRefresh();

}

});

}

public void scroll2TopAndRefresh() {

L.i(this, "scroll2TopAndRefresh");

//TODO 这里需要处理多次连续调用的情况

}

}

```

### 9、ResourcesId注解 [anno.inject](http://github.com/WeiChou/Wei.Lib2A/tree/master/Wei.Lib2A/src/hobby/wei/c/anno/inject)

* 注意`@ViewOnClick`的用法非常灵活。示例:

```Java

@ViewLayoutId(R.layout.m_edit)

public class EditActy extends AbsActivity implements OnClickListener {

@ViewOnClick // 当本类 implements OnClickListener, 那么直接加上本注解即可,不用参数

@ViewId(R.id.m_edit_title_left_btn_back)

private ImageButton mBtnBack;

@ViewId(value = R.id.m_edit_magic_board, visibility = View.GONE) // 多参数

private MagicBoardView mMagicBoard;

@ViewId(name = "m_edit_text", visibility = View.INVISIBLE) // 对于库项目,R.id.xxx非final的情况下,可写name字符串

private TextView mText;

//...

@Override

@ViewOnClick(@Ids(R.id.m_edit_magic_board)) // 若前面没有加@ViewOnClick, 也可以写在onClick()上面,参数也可以像下面这样

@ViewOnClick(@Ids({R.id.m_edit_title_left_btn_back, R.id.m_edit_magic_board}))

public void onClick(View v) {

switch (v.getId()) {

case R.id.m_acty_btn_download:

//...

break;

}

@ViewOnClick(@Ids({R.id.m_edit_title_left_btn_back, R.id.m_edit_magic_board})) // 或者可以写在任意自定义方法上面

private void myOnClick(View v) { // 这里也可以不用参数,像这样: private void myOnClick() {}

//...

}

@ViewOnClick(@Ids({R.id.m_edit_title_left_btn_back, R.id.m_edit_magic_board})) //甚至还可以这样,有没有觉得很cool

private OnClickListener mOnClickListener = new OnClickListener() {

@Override

public void onClick(View v) {

//...

}

};

}

```

### 10、Json的抽象 [IJson](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/data/abs)

示例:

```Java

/**由于typeKey可能全局都一样,做一个抽象**/

public abstract class AbsData> extends AbsJsonTyped {

public static final String KEY_RESULT= "result";

@Expose

public String result;

protected String typeKey() {

return KEY_RESULT;

}

}

/**构建与Json字符串对应的类结构**/

public class EditBean extends AbsData {

@Expose

public long id;

@Expose

public long topicId;

@Expose

public boolean favorite;

@Expose

public Info info;

public boolean selected = false;

public static class Info {

public Temp[] temps;

public int total_number;

}

public static class Temp {

public long mid;

public MagicBoardBody body;

public int forwarding_count;

public int classify;

public long start_time;

public long end_time;

public int collect;

}

public EditBean() {}

@Override

public int hashCode() {

return (int)id;

}

@Override

public boolean equals(Object o) {

EditBean fb = ((EditBean)o);

return fb.id == id && fb.topicId == topicId;

}

@Override

public EditBean fromJson(String json) {

return fromJsonWithExposeAnnoFields(json, getTypeToken());

}

@Override

public String toJson() {

return toJsonWithExposeAnnoFields(this);

}

@Override

protected String[] typeValues() {

return null;

}

@Override

protected TypeToken getTypeToken() {

return new TypeToken(){};

}

}

/*以下为操作数据*/

EditBean edit = new EditBean();

//edit.xxx = xxx;

//...

//序列化

edit.toJson();

//判断是否属于本类型,一般情况用不到。

if (new EditBean().isBelongToMe(new JSONObject(jsonString))) {

//...

}

//反序列化

new EditBean().fromJson(jsonString);

```

### 11、用途广泛的 [ViewHolder](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/framework/ViewHolder.java)

既可用于`ListView`的`Adapter`:

```Java

@Override

public View getView(int position, View convertView, ViewGroup parent) {

return EditGridViewHolder.getAndBindView(position, convertView, parent, getInflater(), EditGridViewHolder.class, getItem(position), mOnFavoriteClick);

}

//...

@ViewLayoutId(R.layout.i_m_edit)

public static class EditGridViewHolder extends ViewHolder {

@ViewId(R.id.i_m_edit_magic_board)

private MagicBoardView mMagicBoard;

@ViewId(R.id.i_m_edit_cb_favorite)

private CheckBox mCBFav;

private Animation mAnimYes, mAnimNo;

private boolean mAnimYesStarted = false, mAnimNoStarted = false;

public EditGridViewHolder(View view) {

super(view);

}

@Override

protected void init(OnClickListener... args) {

mCBFav.setOnClickListener(args[0]);

}

@Override

public void bind(int position, EditListBean data) {

mCBFav.setTag(this);

MagicBoardUtils.display(getView().getContext(), mMagicBoard, data.magicBoard);

mPanelTranslucence.setVisibility(data.selected ? View.VISIBLE : View.GONE);

updateFavorite(false);

}

//...

}

```

也可用于`ViewPager`的`PagerAdapter`:

```Java

mViewPager.setAdapter(new PagerAdapter() {

@Override

public int getCount() {

return 5;

}

@Override

public boolean isViewFromObject(View view, Object obj) {

return view == ((ViewHolder, ?>)obj).getView();

}

@Override

public int getItemPosition(Object obj) {

int position = super.getItemPosition(obj);

if (obj instanceof ViewHolder4) {

position = 4;

} else if (obj instanceof ViewHolder3) {

position = 3;

} else if (obj instanceof ViewHolder2) {

position = 2;

} else if (obj instanceof ViewHolder1) {

position = 1;

} else if (obj instanceof ViewHolder0) {

position = 0;

}

return position;

}

@Override

public Object instantiateItem(ViewGroup container, int position) {

ViewHolder vHolder = null;

switch (position) {

case 0:

vHolder = ViewHolder.bindView(0, ViewHolder.makeView(ViewHolder0.class, getLayoutInflater(), container), ViewHolder0.class, null, mOnNextClick);

break;

case 1:

vHolder = ViewHolder.bindView(0, ViewHolder.makeView(ViewHolder1.class, getLayoutInflater(), container), ViewHolder1.class, null, mOnNextClick);

break;

case 2:

vHolder = ViewHolder.bindView(0, ViewHolder.makeView(ViewHolder2.class, getLayoutInflater(), container), ViewHolder2.class, null, mOnNextClick);

break;

case 3:

vHolder = ViewHolder.bindView(0, ViewHolder.makeView(ViewHolder3.class, getLayoutInflater(), container), ViewHolder3.class, null, mOnNextClick);

break;

case 4:

vHolder = ViewHolder.bindView(0, ViewHolder.makeView(ViewHolder4.class, getLayoutInflater(), container), ViewHolder4.class, null, mOnCompleteClick);

break;

}

container.addView(vHolder.getView());

return vHolder;

}

@Override

public void destroyItem(ViewGroup container, int position, Object obj) {

container.removeView(((ViewHolder, ?>)obj).getView());

}

});

}

//...

@ViewLayoutId(R.layout.i_m_guide_next)

private static class ViewHolder0 extends ViewHolder {

@ViewId(R.id.i_m_guide_bg)

protected View mBg;

@ViewId(R.id.i_m_guide_btn_next)

protected ImageButton mBtnNext;

protected static final int WIDTH= 720;

protected static final int HEIGHT= 1280;

protected static final int WIDTH_BTN= 224;

protected static final int HEIGHT_BTN= 88;

protected static final int RIGHT_BTN= 16;

protected static final int BOTTOM_BTN= 29;

public ViewHolder0(View view) {

super(view);

}

@Override

protected void init(OnClickListener... args) {

mBg.setBackgroundResource(R.drawable.img_i_m_guide_0);

mBtnNext.setTag(0);

mBtnNext.setOnClickListener(args[0]);

initBtnNextPosition();

}

@Override

public void bind(int position, Void data) {}

protected void initBtnNextPosition() {

int screenWidth = Device.getInstance(getView().getContext()).width;

int screenHeight = Device.getInstance(getView().getContext()).height;

RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mBtnNext.getLayoutParams();

float widthScale = screenWidth * 1.0f / WIDTH;

float heightScale = screenHeight * 1.0f / HEIGHT;

lp.width = (int) (widthScale * WIDTH_BTN);

lp.height = (int) (heightScale * HEIGHT_BTN);

lp.rightMargin = (int) (widthScale * RIGHT_BTN);

lp.bottomMargin = (int) (heightScale * BOTTOM_BTN);

mBtnNext.setLayoutParams(lp);

}

}

private static class ViewHolder1 extends ViewHolder0 {

public ViewHolder1(View view) {

super(view);

}

@Override

protected void init(OnClickListener... args) {

mBg.setBackgroundResource(R.drawable.img_i_m_guide_1);

mBtnNext.setTag(1);

mBtnNext.setOnClickListener(args[0]);

initBtnNextPosition();

}

}

//...

```

还可用于其他任何场景:

```Java

public class Xxx {

@Override

public void onClick(View v) {

//弹出删除对话框

FavoriteDeleteViewHolder.showDeleteDialog(FavoriteActy.this, (ViewGroup)getWindow().getDecorView(), mOnDeleteClick);

}

//...

}

@ViewLayoutId(R.layout.m_favorite_delete_panel)

public class FavoriteDeleteViewHolder extends ViewHolder {

@ViewId(R.id.m_favorite_delete_panel_content)

private ViewGroup mContentView;

@ViewId(R.id.m_favorite_delete_panel_btn_delete)

private Button mBtnDelete;

@ViewId(R.id.m_favorite_delete_panel_btn_cancel)

private Button mBtnCancel;

private Context mContext;

private OnClickListener mOnDeleteClickCallback;

private boolean mDelete;

public FavoriteDeleteViewHolder(View view) {

super(view);

mContext = view.getContext();

}

public static FavoriteDeleteViewHolder showDeleteDialog(Activity context, ViewGroup parent, OnClickListener onDeleteClickCallback) {

View view = FavoriteDeleteViewHolder.makeView(FavoriteDeleteViewHolder.class, context.getLayoutInflater(), parent);

FavoriteDeleteViewHolder vHolder = FavoriteDeleteViewHolder.bindView(0, view, FavoriteDeleteViewHolder.class, null, onDeleteClickCallback);

parent.addView(view);

vHolder.startAnimIn();

return vHolder;

}

public void destroy() {

startAnimOut();

}

//...

}

```

* 简直神乎其技呀,有木有?!!!

### 12、相册选择图片、剪裁,保存图片到相册并广播刷新 [PhotoUtils](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/utils/PhotoUtils.java)

示例:

```Java

private static final String EXTRA_SESSION = ContributeActy.class.getName() + ".SESSION";

private static final String EXTRA_LIST_DATA = ContributeActy.class.getName() + ".LIST_DATA";

private static final int REQUEST_CODE_PICK_PHOTO = 100;

private static final int REQUEST_CODE_CROP = 101;

private PhotoUtils.Session session;

//...

@Override

public void onClick(View v) {

try {

session = PhotoUtils.openSysGallery2ChoosePhoto(ContributeActy.this, REQUEST_CODE_PICK_PHOTO,

new CropArgs(REQUEST_CODE_CROP,

new File(App.getImagesCacheDirPrivate(), "croptemp-" + System.currentTimeMillis() + ".png").getPath(),

Bitmap.CompressFormat.PNG, false, true, 0, 0, 0, 0, 640, 640));

L.i(ContributeActy.class, session.toString());

} catch (Exception e) {

L.e(ContributeActy.class, e);

}

}

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

super.onActivityResult(requestCode, resultCode, data);

Uri uri = PhotoUtils.onActivityResult(this, session, requestCode, resultCode, data);

if (uri != null) {

getAdapter().getData().add(uri);

getAdapter().notifyDataSetChanged();

session = null;

}

}

@Override

protected void onSaveInstanceState(Bundle outState) {

List data = getAdapter().getData();

if (data.size() > 0) {

ArrayList value = new ArrayList();

for (Uri uri : data) {

value.add(uri.toString());

}

outState.putStringArrayList(EXTRA_LIST_DATA, value);

}

if (session != null) outState.putString(EXTRA_SESSION, session.toJson());

super.onSaveInstanceState(outState);

}

@Override

protected void onRestoreInstanceState(Bundle savedInstanceState) {

super.onRestoreInstanceState(savedInstanceState);

ArrayList value = savedInstanceState.getStringArrayList(EXTRA_LIST_DATA);

if (value != null && value.size() > 0) {

List data = new ArrayList();

for (String s : value) {

data.add(Uri.parse(s));

}

getAdapter().setDataSource(data);

}

String json = savedInstanceState.getString(EXTRA_SESSION);

if (json != null) session = Session.fromJsonWithAllFields(json, Session.class);

}

```

### 13、简化ListView及同类组件数据更新的套件 [AbsListViewActivity](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/framework/AbsListViewActivity.java)、[AbsListViewFragment](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/framework/AbsListViewFragment.java) 和 [AbsAdapter](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/adapter/AbsAdapter.java)

示例:

```Java

@ViewLayoutId(R.layout.m_edit)

@ViewListId(R.id.m_edit_grid_view)

public class EditActy extends AbsListViewActivity {

private static final String EXTRA_CATEGORY_ID= EditActy.class.getName() + ".EXTRA_CATEGORY_ID";

public static void startMe(Context context, long categoryId) {

Intent intent = new Intent(context, EditActy.class);

intent.putExtra(EXTRA_CATEGORY_ID, categoryId);

startMe(context, intent);

}

@ViewId(R.id.m_edit_title_left_btn_back)

private ImageButton mBtnBack;

@ViewId(R.id.m_edit_magic_board)

private MagicBoardView mMagicBoard;

@Override

protected EditGridAdapter newAdapter() {

return new EditGridAdapter(this, mOnFavoriteClick);

}

//...

}

```

### 14、图像工具 [BitmapUtils](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/utils/BitmapUtils.java)

### 15、AndroidManifest.xml属性读取工具 [Manifest](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/utils/Manifest.java)

### 16、对话框、弹窗和进度条 [DialogHelper、Prompt 和 PromptProgress](http://github.com/WeiChou/Wei.Lib2A/tree/master/Wei.Lib2A/src/hobby/wei/c/widget/)

* UI和动画都可全局定制;

* `DialogHelper`可弹出在桌面上。

### 17、文本超链接点击效果 [LinkMovementMethod、LinkSpan](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/widget/text)

### 18、具有退出监听能力的 [AbsApp](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/framework/AbsApp.java)

```Java

public class App extends AbsApp {

@Override

protected boolean onExit() {

L.i(this, "程序正常退出------App.onExit()");

//...

super.onExit();

if (mExitForRestart) {

WelcomeActy.startMe(this);

mExitForRestart = false;

}

return false;

}

//...

}

```

### 19、非对称密钥对生成工具 [RsaUtils](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/utils/RsaUtils.java)

* 可生成iOS项目能识别的公钥密钥文件(iOS要求比较苛刻,而java的库对密钥文件的识别能力较强)。

###20、时间工具 [TimeUtils](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/utils/TimeUtils.java)

* 可解析C#生成的Java标准API`SimpleDateFormat`无法识别的格式化字符串如`2013-05-22T09:16:44.871589GMT+0800`和`2013-05-22T09:16:44.871589+08:00`;

* 可根据生日计算年龄;

* 可生成无时区的时间长度表示,并定制单位,如:3天前,1周前,2年6个月前等;

* 可根据系统时间返回凌晨、上午、中午、下午、晚上、晚休等信息。

### 21、Log的简化版[ L ](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/L.java)

* 可在release打包混淆时,将低级别日志自动删除,同时优化掉作为参数的字符串常量(对参数有规范化要求,见代码文档:[@Burden](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/anno/proguard/Burden.java) 或 [proguard.README](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/anno/proguard/README.md))。

### 22、全局异常拦截器 [CrashHandler](http://github.com/WeiChou/Wei.Lib2A/blob/master/Wei.Lib2A/src/hobby/wei/c/utils/CrashHandler.java)

* 可dump运行时内存到存储卡(.hprof文件)用于内存分析;

* 可拦截某线程的某异常或所有异常;

* 可拦截所有线程的某异常或所有异常;

* 拦截后的处理方式应该根据业务需要自定义处理,默认是作闪退处理。

### 23、全新基于`@Annotation`的混淆配置库

* 已独立迁移至github并上传jcenter: [Annoguard](http://github.com/WeiChou/Annoguard)

#### 联系作者

![微信](weichat_qr_code.jpg)

![支付宝](zhifubao_qr_code.jpg)

一键复制

编辑

Web IDE

原始数据

按行查看

历史

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值