摘要:一個(gè)非常小型的項(xiàng)目,但是該有的都有。快速跳轉(zhuǎn)至頂部,底部,指定位置。讀寫緩存的效率遠(yuǎn)低于,所以采用實(shí)現(xiàn)的緩存機(jī)制,速度快了大概,倍。序列化性能性能測(cè)試,,為了避免干擾,我們使用進(jìn)行測(cè)試。
一個(gè)非常小型的Kotlin項(xiàng)目,但是該有的都有。如果您覺得有意思就幫我star下,人多了我就會(huì)放更多的福利哦。github
先上福利。Release1.0
特點(diǎn)列表顯示圖片,點(diǎn)擊查看更多。
快速跳轉(zhuǎn)至頂部,底部,指定位置。
收藏,查看歷史記錄。
設(shè)置壁紙。
離線緩存。
組成語言:Kotlin,Java
網(wǎng)絡(luò)請(qǐng)求:HttpUrlConnection
數(shù)據(jù)庫:Sqlite
數(shù)據(jù)源:Jsoup
第三方庫:Glide
概述1) 網(wǎng)絡(luò)請(qǐng)求
網(wǎng)絡(luò)框架并沒有使用RxRetrofit等,為了保證精簡(jiǎn)高效直接使用的HttpUrlConnection
get
val request = AsyncNetwork() request.request(Constants.HOST_MOBILE_URL, null) request.setRequestCallback(object : IRequestCallback { override fun onSuccess(httpURLConnection: HttpURLConnection?, response: String) { //todo } })
post
val request = AsyncNetwork() request.request(Constants.HOST_MOBILE_URL, mutableMapOf()) request.setRequestCallback(object : IRequestCallback { override fun onSuccess(httpURLConnection: HttpURLConnection?, response: String) { //todo } })
2) 數(shù)據(jù)庫
數(shù)據(jù)庫沒有使用第三方框架,直接使用的sql語句。
CREATE TABLE tb_class_page_list ( _id INTEGER PRIMARY KEY ASC AUTOINCREMENT, href STRING UNIQUE, description STRING, image_url STRING, id_class_page INTEGER REFERENCES tb_class_page (_id) ON DELETE CASCADE ON UPDATE CASCADE, [index] INTEGER);
3) 讀寫緩存
Serializable的效率遠(yuǎn)低于Parcelable,所以采用Parcelable實(shí)現(xiàn)的緩存機(jī)制,速度快了大概7,8倍。
讀取緩存
val helper = PageListCacheHelper(container?.context?.filesDir?.absolutePath) val pageModel: Any? = helper.get(key)
寫入緩存
val helper = PageListCacheHelper(context.filesDir.absolutePath) helper.put(key, object)
刪除緩存
val helper = PageListCacheHelper(context.filesDir.absolutePath) helper.remove(key)
4) jsoup獲取數(shù)據(jù)
由于數(shù)據(jù)是用從html頁面中提取的,所以速度偏慢,為了不影響體驗(yàn)做了一套緩存機(jī)制,來做到流暢體驗(yàn)。
Document doc = Jsoup.parse(html); Elements elements = body.getElementsByTag("a"); String text = elements.get(0).text(); String imageUrl = elements.get(0).attr("src"); ...
5) 組件
Activity fragment替代activity來顯示新界面
因?yàn)閍ctivity需要在Manifiest中注冊(cè),所以當(dāng)有多個(gè)activity的時(shí)候,就需要編寫很長(zhǎng)的Manifiest文件,嚴(yán)重影響了Manifiest的可讀性,界面的風(fēng)格也比較笨重。所以一個(gè)新頁面就注冊(cè)一個(gè)activity不太合適,我們通過用activity做為容器添加不同的Fragment來達(dá)到注冊(cè)一個(gè)activity啟動(dòng)多個(gè)不同頁面的效果。生命周期由activity管理,更方便簡(jiǎn)潔。
open class BaseFragmentActivity : BaseActionActivity() { companion object { private const val EXTRA_FRAGMENT_NAME = "extra_fragment_name" private const val EXTRA_FRAGMENT_ARG = "extra_fragment_arguments" @JvmOverloads @JvmStatic fun newInstance(context: Context, fragment: Class<*>, bundle: Bundle? = null, clazz: Class= getActivityClazz()): Intent { val intent = Intent(context, clazz) intent.putExtra(EXTRA_FRAGMENT_NAME, fragment.name) intent.putExtra(EXTRA_FRAGMENT_ARG, bundle) return intent } protected open fun getActivityClazz(): Class { return BaseFragmentActivity::class.java } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.cc_activity_base_fragment) val fragmentName = intent.getStringExtra(EXTRA_FRAGMENT_NAME) var fragment: Fragment? = null if (TextUtils.isEmpty(fragmentName)) { //set default fragment //fragment = makeFragment(MainFragment::class.java!!.getName()) } else { val args = intent.getBundleExtra(EXTRA_FRAGMENT_ARG) try { fragment = makeFragment(fragmentName) if (args != null) fragment?.arguments = args } catch (e: Exception) { e.printStackTrace() } } if (fragment == null) return supportFragmentManager .beginTransaction() .replace(R.id.fragment_container, fragment) .commit() } fun makeFragment(name: String): Fragment? { try { val fragmentClazz = Class.forName(name) return fragmentClazz.newInstance() as Fragment } catch (e: Exception) { e.printStackTrace() } return null } }
6) 序列化性能
性能測(cè)試,Serializable VS Externalizable,為了避免干擾,我們使用AndroidTest進(jìn)行測(cè)試。
模型
class Model1 implements Serializable { String text; int code; boolean bool; Model1 child; } class Model2 extends Model1 implements Externalizable { public Model2() { } @Override public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException { text = input.readUTF(); code = input.readInt(); bool = input.readBoolean(); child = new Model2(); child.text = input.readUTF(); child.code = input.readInt(); child.bool = input.readBoolean(); } @Override public void writeExternal(ObjectOutput output) throws IOException { output.writeUTF(text); output.writeInt(code); output.writeBoolean(bool); if (child != null) { output.writeUTF(child.text); output.writeInt(child.code); output.writeBoolean(child.bool); } } }
測(cè)試
@Test public void serializableVSExternalizable() throws Exception { ListtestModel1 = new ArrayList<>(); for (int i = 0; i < 50000; i++) { Model1 model1 = new Model1(); model1.text = "Hello World " + i; model1.code = i; model1.bool = false; Model1 child = new Model1(); child.text = "Hello World Child" + i; child.code = i; child.bool = false; model1.child = child; testModel1.add(model1); } long startTime = System.currentTimeMillis(); File file = new File("/sdcard/serializable"); ObjectOutputStream oStream = new ObjectOutputStream(new FileOutputStream(file)); oStream.writeObject(testModel1); oStream.close(); Log.e("serializable", "write time " + (System.currentTimeMillis() - startTime)); startTime = System.currentTimeMillis(); ObjectInputStream iStream = new ObjectInputStream(new FileInputStream(file)); testModel1 = (List ) iStream.readObject(); iStream.close(); Log.e("serializable", "read time " + (System.currentTimeMillis() - startTime)); testModel1 = null; List testModel2 = new ArrayList<>(); for (int i = 0; i < 50000; i++) { Model2 model2 = new Model2(); model2.text = "Hello World " + i; model2.code = i; model2.bool = false; Model2 child = new Model2(); child.text = "Hello World Child" + i; child.code = i; child.bool = false; model2.child = child; testModel2.add(model2); } startTime = System.currentTimeMillis(); file = new File("/sdcard/externalizable"); oStream = new ObjectOutputStream(new FileOutputStream(file)); oStream.writeObject(testModel2); oStream.close(); Log.e("externalizable", "write time " + (System.currentTimeMillis() - startTime)); startTime = System.currentTimeMillis(); iStream = new ObjectInputStream(new FileInputStream(file)); testModel2 = (List ) iStream.readObject(); iStream.close(); Log.e("externalizable", "read time " + (System.currentTimeMillis() - startTime)); }
結(jié)果
序列化5000個(gè)對(duì)象 Serializable:寫入耗時(shí)4026 ms,讀取耗時(shí)177 ms Externalizable:寫入耗時(shí)2680 ms,讀取耗時(shí)79 ms 序列化50000個(gè)對(duì)象 Serializable:寫入耗時(shí)46872 ms,讀取耗時(shí)1807 ms Externalizable:寫入耗時(shí)41334 ms,讀取耗時(shí)792 ms
從結(jié)果上可以看到Externalizalbe相比于Serializable是稍微快一些點(diǎn)不管是寫入還是讀取速度。對(duì)象存儲(chǔ)還可以使用一些對(duì)象關(guān)系映射(ORM)型的數(shù)據(jù)庫。如GreenDao等等。
7) Java中的深拷貝
由于System.arrayCopy()該方法拷貝數(shù)組的時(shí)候,如果是基本數(shù)據(jù)類型則是深拷貝,如果是對(duì)象類型則會(huì)是淺拷貝,無法做到深拷貝,所以想深拷貝一個(gè)數(shù)組就得循環(huán)創(chuàng)建對(duì)象并賦值,這顯得很麻煩。所以項(xiàng)目中使用序列化的方法進(jìn)行深拷貝。PS:Serializable序列化方式讀取的時(shí)候并不會(huì)調(diào)用對(duì)象構(gòu)造方法,而Externalizable序列化方式讀取時(shí)會(huì)調(diào)用對(duì)象的無參構(gòu)造方法。
@SuppressWarnings("unchecked") public staticT deepCopyOrThrow(T src) throws IOException, ClassNotFoundException { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(src); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream in = new ObjectInputStream(byteIn); return (T) in.readObject(); } public static T deepCopy(T src) { try { return deepCopyOrThrow(src); } catch (Exception ignore) { ignore.printStackTrace(); return null; } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/68026.html
閱讀 3205·2021-11-08 13:21
閱讀 1196·2021-08-12 13:28
閱讀 1406·2019-08-30 14:23
閱讀 1924·2019-08-30 11:09
閱讀 840·2019-08-29 13:22
閱讀 2684·2019-08-29 13:12
閱讀 2549·2019-08-26 17:04
閱讀 2250·2019-08-26 13:22