开源软件名称:Wei.Lib2A
开源软件地址:https://gitee.com/wei.chou/Wei.Lib2A
开源软件介绍:
Wei.Lib2A
2016年新增内容: 全新基于@Annotation 的混淆配置库
Android快速开发库,Android常用工具集。任务管理、数据加载、下载库请查阅其他项目。 对于初学者欢迎加 QQ群:215621863 相互学习探讨! 这个库都有什么?能帮我们做什么?我写代码遵循两个基本原则:- 减少代码量。希望达到的效果是,让使用者尽可能减少代码,能一句话搞定的,绝不两句,能静态方法搞定的,绝不new对象;
- 增强适应性和稳定性。由于Android平台厂商定制的碎片化和众多版本兼容性问题,本库的开发会着重考虑这些因素,而且基本都是经上线的项目考验过的。
本库的所有代码都经过本人严格测试,字斟句酌,了如指掌,注释也很清晰。覆盖Android基础开发的方方面面,推荐作为项目的基础框架来使用,以便于各功能的正常便利集成。有任何疑问或建议请联系作者:[email protected]、微信 或 加群@群主。 基础常用组件介绍如下:仅通过几个常量即可便捷的取得内置或外置存储卡 Storage.SdCard 对象。例如: //输出外置存储卡的路径到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); } } 仅有存储卡工具 就够了吗?它需要去判断存储卡是否存在、能否创建目录和文件,再决定是否写文件。而FStoreLoc 可以一步完成: public static File getImagesCacheDir() throws SdCardNotMountedException, SdCardNotValidException, FileCreateFailureException { return FStoreLoc.BIGFILE.getImagesCacheDir(get(), DirLevel.CUSTOM); } FStoreLoc 有三种预置存储模式:
而大文件模式 和生存模式 根据业务需要可能需要设置存储卡根目录,那就放在App初始化里: 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); } //... } 4、增强的SharedPreferences工具:Keeper具有多进程读写安全、基于Locale的文件隔离能力等。 基本用法: 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(); 示例: @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) {} } 基于但简化了Broadcast 和LocalBroadcast 的发送/接收操作,在页面初始化的时候可以调用AbsActivity/AbsFragment.hostingLocalEventReceiver(...)将事件监听器进行托管,不再需要在onPause() 、onResume() 以及onDestroy() 等事件的时候进行unregisterXxx() 和registerXxx() 编码,托管组件将自动完成。受惠于Broadcast 的松散耦合机制和简化了的发送/接收操作,可将传统的Callack 模式用本事件模式重构,轻松解决由于某些原因导致的资源无法释放 和内存泄露 等问题。示例: //在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 这里需要处理多次连续调用的情况 } } - 注意
@ViewOnClick 的用法非常灵活。示例:
@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示例: /**由于typeKey可能全局都一样,做一个抽象**/ public abstract class AbsData<T extends AbsData<T>> extends AbsJsonTyped<T> { public static final String KEY_RESULT = "result"; @Expose public String result; protected String typeKey() { return KEY_RESULT; } } /**构建与Json字符串对应的类结构**/ public class EditBean extends AbsData<EditBean> { @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<EditBean> getTypeToken() { return new TypeToken<EditBean>(){}; } } /*以下为操作数据*/ EditBean edit = new EditBean(); //edit.xxx = xxx; //... //序列化 edit.toJson(); //判断是否属于本类型,一般情况用不到。 if (new EditBean().isBelongToMe(new JSONObject(jsonString))) { //... } //反序列化 new EditBean().fromJson(jsonString); 既可用于ListView 的Adapter : @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<EditBean, OnClickListener> { @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
|
请发表评论