http://blog.csdn.net/banketree/article/details/25589833
简介
一个好的Android应用开发框架,可以加快Android开发速度,今天笔记基于许多开源项目自写了一款Android应用框架。
内容
框架包括:界面管理(Activity管理)、数据库操作(orm框架、加密等)、http交互、缓存管理、下载管理、路径管理、日志输出、网络管理、系统命令、加解密、stl容器、任务管理、奔溃管理、存储管理、其它辅助管理…。
解决思路如下:
界面管理:使用Stack记录Activity的运行轨迹,并在每个Activity添加一个广播处理自定义事件。
- private static Stack<Activity> mActivityStack;//进行Activity运行记录
http交互:实现http交互方式有同步、异步操作。采用的是android-async-http开源项目解决。
缓存管理:实现缓存方式有内存缓存、磁盘缓存。其中内存缓存只针对图片处理,磁盘缓存是针对某目录,实现的方式有:先进先出、最大量、使用频率等。
下载管理:下载管理方式有多线程下载、单线程下载。
路径管理:简单的说就是对程序的目录管理,分图片、视频、音频、缓存目录等。
日志输出:基于Log的管理(分调式、发布模式和文件输出、log输出)。
网络管理:2G、3G、4G等联网方式不同的管理和监听。
系统命令:直接命令运行。
加解密:aes、base64、des、md5等加密方式。
stl容器:重写stl部分容器。
任务管理:基于AsyncTask任务的管理。
奔溃管理:捕捉奔溃信息,并提供发送接口。采用的是acra方法解决。
存储管理:主要是SharedPreferences和Properties的管理。
其它辅助管理:版本、内存、手机格式、字符串操作……等等。
项目如图:
效果如图:
+
相关测试代码:
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.test_tree);
- TFilePathManager.getInstance().initConfig(null); // 默认目录(下载�?图片、视频�?缓存等目�?
- // 优先考虑内存条,其次手机内存�?
- }
- public void onClickTestPath(View view) { // 测试路径
- TFilePathManager.getInstance().initConfig(
- Environment.getExternalStorageDirectory().getPath()
- + File.pathSeparator + "test");
- // 程序目录里面分了图片、缓存区、下载图、音频区、视频区
- TFilePathManager.getInstance().getAppPath();
- TFilePathManager.getInstance().getAudioPath();
- TFilePathManager.getInstance().getCachePath();
- TFilePathManager.getInstance().getDownloadPath();
- TFilePathManager.getInstance().getImagePath();
- }
- public void onClickTestLog(View view) { // 测试日志
- TLog.enablePrintToFileLogger(true);
- for (int i = 0; i < 100; i++)
- TLog.i(TAG, "123456" + i);
- // TLog.release(); //关闭程序可释�?
- // 日志是放在程序目录下
- // TLog.enableIgnoreAll(enable);
- // TLog.enableIgnoreWarn(enable);
- }
- public void onClickTestTActivity(View view) { // 测试TActivity
- Intent intent = new Intent();
- intent.setClass(this, TestTActivity.class);
- startActivity(intent);
- }
- public void onClickTestHttp1(View view) { // 测试Http1
- Intent intent = new Intent();
- intent.setClass(this, TestHttp1.class);
- startActivity(intent);
- }
- public void onClickTestHttp2(View view) { // 测试Http2
- Intent intent = new Intent();
- intent.setClass(this, TestHttp2.class);
- startActivity(intent);
- }
- public void onClickTestThreadsdown(View view) { // 测试多线程下载
- Intent intent = new Intent();
- intent.setClass(this, TestDowns.class);
- startActivity(intent);
- }
- public void onClickTestCrash(View view) { // 崩溃
- int result = 1 / 0;
- }
- public void onClickTestSqlEncrypt(View view) { // 测试sql加密
- Intent intent = new Intent();
- intent.setClass(this, TestSqlEncrypt.class);
- startActivity(intent);
- }
- public void onClickTestDAO(View view) { // 测试orm数据库
- Intent intent = new Intent();
- intent.setClass(this, TestDAO.class);
- startActivity(intent);
- }
- public void onClickTestDB(View view) { // 测试Think数据库
- Intent intent = new Intent();
- intent.setClass(this, TestDB.class);
- startActivity(intent);
- }
- public void onClickTestCache(View view) { // 测试缓存
- Intent intent = new Intent();
- intent.setClass(this, TestCache.class);
- startActivity(intent);
- }
- public void onClickTConfig(View view) { // 测试配置信息
- TPreferenceConfig.getInstance().initConfig(this);
- TPropertiesConfig.getInstance().initConfig(this);
- TIConfig iConfig = TPreferenceConfig.getInstance();
- iConfig.setBoolean("123", true);
- boolean result = iConfig.getBoolean("123", false);
- iConfig = TPropertiesConfig.getInstance();
- iConfig.setBoolean("1234", true);
- result = iConfig.getBoolean("1234", false);
- }
- public void onClickEncryption(View view) { // 测试加密
- String src = "banketree@qq.com";
- String encrypted = "";
- String key = "banketree";
- try {
- encrypted = TAes.encrypt(key, src);
- String tempString = TAes.decrypt(key, encrypted);
- encrypted = TBase64.encode(src.getBytes());
- tempString = TBase64.decode(encrypted).toString();
- encrypted = TDes.encrypt(key, src);
- tempString = TDes.decrypt(key, encrypted);
- TLog.i(this, tempString);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public void onClickZip(View view) { // 测试解压缩
- try {
- TCompressUtils.compressJar("");
- TCompressUtils.compressZip("");
- TCompressUtils.uncompressJar("");
- TCompressUtils.uncompressZip("");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
奔溃处理回调:
- @Override
- public void onAppCrash(String crashFile) {
- TLog.d(TAG, "Creating Dialog for " + crashFile);
- Intent dialogIntent = new Intent(this, TestCrash.class);
- dialogIntent.putExtra(TCrash.EXTRA_REPORT_FILE_NAME, crashFile);
- dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(dialogIntent);
- }
- mMemoryCacheSize = 2 * 1024 * 1024;// 2M
- mDiscCacheSize = 2 * 1024 * 1024;// 2M
- mDiscCacheFileCount = 100;// 一百个文件
- mMemoryCache = TCacheManager.createLruMemoryCache(mMemoryCacheSize);
- try {
- mDiscCache1 = TCacheManager.createReserveDiscCache(TFilePathManager
- .getInstance().getCachePath(), "test");
- } catch (Exception e) {
- e.printStackTrace();
- }
- try {
- mDiscCache2 = TCacheManager.createFileCountLimitedDiscCache(
- mDiscCacheFileCount, TFilePathManager.getInstance()
- .getCachePath());
- } catch (Exception e) {
- e.printStackTrace();
- }
- try {
- Drawable demo = getResources().getDrawable(R.drawable.ic_launcher);
- Bitmap bitmap = ((BitmapDrawable) demo).getBitmap();
- if (arg0 == mTest1Button) {
- mMemoryCache.put("123", bitmap);
- mMemoryCache.put("1234", bitmap);
- mMemoryCache.get("123");
- mMemoryCache.get("1234");
- } else if (arg0 == mTest2Button) {
- mDiscCache1.put("123", mContext.getCacheDir());
- mDiscCache1.get("123");
- } else if (arg0 == mTest3Button) {
- mDiscCache2.put("123", mContext.getCacheDir());
- mDiscCache2.get("123");
- }
- } catch (Exception e) {
- makeText(e.getMessage());
- }
Activity之间的通信:
- @Override
- public void onClick(View arg0) {
- if (testComparatorButton == arg0) {
- Log.i("", "");
- UIBroadcast.sentEvent(mContext, 1001, 1002, "");
- }
- }
- @Override
- public void processEvent(Intent intent) {
- super.processEvent(intent);
- int mainEvent = intent.getIntExtra(UIBroadcast.MAINEVENT, -1); // 主事�?
- int subEvent = intent.getIntExtra(UIBroadcast.EVENT, -1);// 次事�?
- makeText("哈哈触发�?" + mainEvent + subEvent);// 每个Activity可接收广�?
- }
Http同步异步请求:
- if (view == mCancelButton) {
- mTAsyncHttpClient.cancelRequests(this, true);
- mTAsyncHttpClient.cancelAllRequests(true);
- } else if (view == mGetButton) {
- url = "https://httpbin.org/get";
- mTAsyncHttpClient.get(url, new AsyncHttpResponseHandler() {
- @Override
- public void onSuccess(int statusCode, Header[] headers,
- byte[] responseBody) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugResponse(new String(responseBody));
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- byte[] responseBody, Throwable error) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- if (responseBody != null) {
- debugResponse(new String(responseBody));
- }
- TLog.e(this, error.getMessage());
- }
- @Override
- public void onProgress(int bytesWritten, int totalSize) {
- super.onProgress(bytesWritten, totalSize);
- }
- @Override
- public void onRetry(int retryNo) {
- makeText(String.format("Request is retried, retry no. %d",
- retryNo));
- }
- });
- } else if (view == mPostButton) {
- url = "http://httpbin.org/post";
- mTAsyncHttpClient.post(mContext, url, getRequestHeaders(),
- getRequestEntity(), null, new AsyncHttpResponseHandler() {
- @Override
- public void onStart() {
- }
- @Override
- public void onSuccess(int statusCode, Header[] headers,
- byte[] response) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugResponse(new String(response));
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- byte[] errorResponse, Throwable e) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugThrowable(e);
- if (errorResponse != null) {
- debugResponse(new String(errorResponse));
- }
- }
- });
- } else if (view == mPutButton) {
- url = "http://httpbin.org/put";
- mTAsyncHttpClient.put(this, url, getRequestHeaders(),
- getRequestEntity(), null, new AsyncHttpResponseHandler() {
- @Override
- public void onStart() {
- }
- @Override
- public void onSuccess(int statusCode, Header[] headers,
- byte[] response) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugResponse(new String(response));
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- byte[] errorResponse, Throwable e) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugThrowable(e);
- if (errorResponse != null) {
- debugResponse(new String(errorResponse));
- }
- }
- });
- } else if (view == mDeleteButton) {
- url = "http://httpbin.org/delete";
- mTAsyncHttpClient.delete(this, url, getRequestHeaders(), null,
- new AsyncHttpResponseHandler() {
- @Override
- public void onStart() {
- }
- @Override
- public void onSuccess(int statusCode, Header[] headers,
- byte[] response) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugResponse(new String(response));
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- byte[] errorResponse, Throwable e) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugThrowable(e);
- if (errorResponse != null) {
- debugResponse(new String(errorResponse));
- }
- }
- });
- } else if (view == mFileButton) {
- url = "https://httpbin.org/robots.txt";
- mTAsyncHttpClient.get(this, url, getRequestHeaders(), null,
- new FileAsyncHttpResponseHandler(this) {
- @Override
- public void onStart() {
- }
- @Override
- public void onSuccess(int statusCode, Header[] headers,
- File response) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugFile(response);
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- Throwable throwable, File file) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugThrowable(throwable);
- debugFile(file);
- }
- private void debugFile(File file) {
- if (file == null || !file.exists()) {
- debugResponse("Response is null");
- return;
- }
- try {
- debugResponse(file.getAbsolutePath()
- + "\r\n\r\n"
- + TFileUtils.getStringFromFile(file));
- } catch (Throwable t) {
- TLog.e(TAG,
- "Cannot debug file contents"
- + t.getMessage());
- }
- if (!deleteTargetFile()) {
- TLog.d(TAG, "Could not delete response file "
- + file.getAbsolutePath());
- }
- }
- });
- } else if (view == mGZipButton) {
- url = "http://httpbin.org/gzip";
- mTAsyncHttpClient.get(this, url, null, null,
- new BaseJsonHttpResponseHandler<SampleJSON>() {
- @Override
- public void onStart() {
- }
- @Override
- public void onSuccess(int statusCode, Header[] headers,
- String rawJsonResponse, SampleJSON response) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- if (response != null) {
- debugResponse(rawJsonResponse);
- }
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- Throwable throwable, String rawJsonData,
- SampleJSON errorResponse) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugThrowable(throwable);
- if (errorResponse != null) {
- debugResponse(rawJsonData);
- }
- }
- @Override
- protected SampleJSON parseResponse(String rawJsonData,
- boolean isFailure) throws Throwable {
- return null;
- // return new ObjectMapper().readValues(
- // new JsonFactory().createParser(rawJsonData),
- // SampleJSON.class).next();
- }
- });
- } else if (view == mRedirect302Button) {
- url = "http://httpbin.org/redirect/6";
- HttpClient client = mTAsyncHttpClient.getHttpClient();
- if (client instanceof DefaultHttpClient) {
- // enableRedirects/enableRelativeRedirects/enableCircularRedirects
- mTAsyncHttpClient.setEnableRedirects(true, true, true);
- }
- mTAsyncHttpClient.get(url, new AsyncHttpResponseHandler() {
- @Override
- public void onSuccess(int statusCode, Header[] headers,
- byte[] responseBody) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugResponse(new String(responseBody));
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- byte[] responseBody, Throwable error) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- if (responseBody != null) {
- debugResponse(new String(responseBody));
- }
- TLog.e(this, error.getMessage());
- }
- @Override
- public void onProgress(int bytesWritten, int totalSize) {
- super.onProgress(bytesWritten, totalSize);
- }
- @Override
- public void onRetry(int retryNo) {
- makeText(String.format("Request is retried, retry no. %d",
- retryNo));
- }
- });
- } else if (view == mJsonButton) {
- url = "http://httpbin.org/headers";
- mTAsyncHttpClient.get(this, url, null, null,
- new BaseJsonHttpResponseHandler<SampleJSON>() {
- @Override
- public void onStart() {
- }
- @Override
- public void onSuccess(int statusCode, Header[] headers,
- String rawJsonResponse, SampleJSON response) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- if (response != null) {
- debugResponse(rawJsonResponse);
- }
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- Throwable throwable, String rawJsonData,
- SampleJSON errorResponse) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugThrowable(throwable);
- if (errorResponse != null) {
- debugResponse(rawJsonData);
- }
- }
- @Override
- protected SampleJSON parseResponse(String rawJsonData,
- boolean isFailure) throws Throwable {
- return null;
- // return new ObjectMapper().readValues(
- // new JsonFactory().createParser(rawJsonData),
- // SampleJSON.class).next();
- }
- });
- } else if (view == mLoginButton) {
- url = "http://myendpoint.com";
- RequestParams params = new RequestParams();
- params.put("username", "banketree");
- params.put("password", "111111");
- params.put("email", "banketree@qq.com");
- // params.put("profile_picture", new File("pic.jpg")); // Upload a
- // File
- // params.put("profile_picture2", someInputStream); // Upload
- // anInputStream
- // map = new HashMap<String, String>();
- // map.put("first_name", "James");
- // map.put("last_name", "Smith");
- // params.put("user", map);
- // * Set<String> set = new HashSet<String>(); //
- // unordered collection
- // * set.add("music");
- // * set.add("art");
- // * params.put("like", set); // url params:
- // "like=music&like=art"
- //
- // * List<String> list = new ArrayList<String>(); //
- // Ordered collection
- // * list.add("Java");<>
- // * list.add("C");
- // * params.put("languages", list); // url params:
- // "languages[]=Java&languages[]=C"
- //
- // * String[] colors = { "blue", "yellow" }; // Ordered collection
- // * params.put("colors", colors); // url params:
- // "colors[]=blue&colors[]=yellow"
- // *
- // * List<Map<String, String>> listOfMaps = new
- // ArrayList<Map<String,
- // * String>>();
- // * Map<String, String> user1 = new HashMap<String,
- // String>();
- // * user1.put("age", "30");
- // * user1.put("gender", "male");
- // * Map<String, String> user2 = new HashMap<String,
- // String>();
- // * user2.put("age", "25");
- // * user2.put("gender", "female");
- // * listOfMaps.add(user1);
- // * listOfMaps.add(user2);
- // * params.put("users", listOfMaps); // url params:
- // "users[][age]=30&users[][gender]=male&users[][age]=25&users[][gender]=female"
- // *
- mTAsyncHttpClient.post(url, params, new AsyncHttpResponseHandler() {
- @Override
- public void onStart() {
- }
- @Override
- public void onSuccess(int statusCode, Header[] headers,
- byte[] response) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugResponse(new String(response));
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- byte[] errorResponse, Throwable e) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugThrowable(e);
- if (errorResponse != null) {
- debugResponse(new String(errorResponse));
- }
- }
- });
- } else if (view == mBinaryButton) {
- url = "http://httpbin.org/gzip";
- mTAsyncHttpClient.get(this, url, getRequestHeaders(), null,
- new BinaryHttpResponseHandler() {
- @Override
- public void onStart() {
- }
- @Override
- public String[] getAllowedContentTypes() {
- // Allowing all data for debug purposes
- return new String[] { ".*" };
- }
- public void onSuccess(int statusCode, Header[] headers,
- byte[] binaryData) {
- debugStatusCode(statusCode);
- debugHeaders(headers);
- debugResponse("Received response is "
- + binaryData.length + " bytes");
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- byte[] errorResponse, Throwable e) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugThrowable(e);
- if (errorResponse != null) {
- debugResponse("Received response is "
- + errorResponse.length + " bytes");
- }
- }
- });
- } else if (view == mSynGetButton) {
- url = "https://httpbin.org/delay/6";
- mTSyncHttpClient.get(this, url, getRequestHeaders(), null,
- new AsyncHttpResponseHandler() {
- @Override
- public void onStart() {
- }
- @Override
- public void onSuccess(final int statusCode,
- final Header[] headers, final byte[] response) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugResponse(new String(response));
- }
- @Override
- public void onFailure(final int statusCode,
- final Header[] headers,
- final byte[] errorResponse, final Throwable e) {
- debugHeaders(headers);
- debugStatusCode(statusCode);
- debugThrowable(e);
- if (errorResponse != null) {
- debugResponse(new String(errorResponse));
- }
- }
- });
- } else if (view == mTimeOutButton) {
- url = "http://httpbin.org/delay/6";
- mTAsyncHttpClient.get(this, url, getRequestHeaders(), null,
- new AsyncHttpResponseHandler() {
- private int counter = 0;
- private int id = counter++;
- private SparseArray<String> states = new SparseArray<String>();
- @Override
- public void onStart() {
- setStatus(id, "START");
- }
- @Override
- public void onSuccess(int statusCode, Header[] headers,
- byte[] responseBody) {
- setStatus(id, "SUCCESS");
- }
- @Override
- public void onFinish() {
- setStatus(id, "FINISH");
- }
- @Override
- public void onFailure(int statusCode, Header[] headers,
- byte[] responseBody, Throwable error) {
- setStatus(id, "FAILURE");
- }
- @Override
- public void onCancel() {
- setStatus(id, "CANCEL");
- }
- private synchronized void setStatus(int id,
- String status) {
- String current = states.get(id, null);
- states.put(id, current == null ? status : current
- + "," + status);
- for (int i = 0; i < states.size(); i++) {
- debugResponse(String.format("%d (from %d): %s",
- states.keyAt(i), counter,
- states.get(states.keyAt(i))));
- }
- }
- });
- }
结束
此框架参考了ThinkAndroid,在写此项目之前,笔者一直使用ThinkAndroid框架开发项目,所以很多思想来源于此。Think框架介绍如下:
ThinkAndroid是一个免费的开源的、简易的、遵循Apache2开源协议发布的Android开发框架,其开发宗旨是简单、快速的进行Android应用程序的开发,包含Android mvc、简易sqlite orm、ioc模块、封装Android httpclitent的http模块,具有快速构建文件缓存功能,无需考虑缓存文件的格式,都可以非常轻松的实现缓存,它还基于文件缓存模块实现了图片缓存功能,在android中加载的图片的时候,对oom的问题,和对加载图片错位的问题都轻易解决。他还包括了一个手机开发中经常应用的实用工具类,如日志管理,配置文件管理,android下载器模块,网络切换检测等等工具。
下载地址:https://github.com/white-cat/ThinkAndroid