《移动项目实践》实验报告——Android数据存储
生活随笔
收集整理的這篇文章主要介紹了
《移动项目实践》实验报告——Android数据存储
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
實(shí)驗(yàn)?zāi)康?/h1>
1、熟悉Android五種主要存儲(chǔ)方式的用法,包括共享參數(shù)SharedPreferences、數(shù)據(jù)庫(kù)SQLite、SD卡文件、App的全局內(nèi)存;
2、熟悉重要組件之一的應(yīng)用Application的基本概念與常見用法,以及四大組件之一的內(nèi)容提供器ContentProvider的基本概念與常見用法;
實(shí)驗(yàn)內(nèi)容
“購(gòu)物車”的設(shè)計(jì)與實(shí)現(xiàn)(參考效果圖)
初始效果
手機(jī)商場(chǎng)的商品列表
商品詳情頁(yè)面
添加商品后的購(gòu)物車
實(shí)驗(yàn)過(guò)程(實(shí)驗(yàn)的設(shè)計(jì)思路、關(guān)鍵源代碼等)
源代碼:https://gitee.com/shentuzhigang/mini-project/tree/master/android-shopping
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffdd"android:orientation="vertical" ><include layout="@layout/activity_shopping_title" /><ScrollViewandroid:layout_width="match_parent"android:layout_height="wrap_content" ><FrameLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:padding="5dp" ><LinearLayoutandroid:id="@+id/ll_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="gone" ><LinearLayoutandroid:id="@+id/ll_cart"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" ></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="10dp" ><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center|right"android:text="總金額:"android:textColor="@color/black"android:textSize="17sp" /><TextViewandroid:id="@+id/tv_total_price"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="2"android:gravity="center|left"android:textColor="@color/red"android:textSize="25sp" /><Buttonandroid:id="@+id/btn_settle"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:text="結(jié)算"android:textColor="@color/black"android:textSize="20sp" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_empty"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="gone" ><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="100dp"android:layout_marginTop="100dp"android:gravity="center"android:text="哎呀,購(gòu)物車空空如也,快去選購(gòu)商品吧"android:textColor="@color/black"android:textSize="17sp" /><Buttonandroid:id="@+id/btn_shopping_channel"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="逛逛手機(jī)商場(chǎng)"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout></FrameLayout></ScrollView></LinearLayout> package io.shentuzhigang.demo.shoppingimport android.annotation.SuppressLint import android.app.Activity import android.app.AlertDialog import android.content.Intent import android.graphics.BitmapFactory import android.graphics.Color import android.os.Bundle import android.os.Environment import android.util.Log import android.util.TypedValue import android.view.* import android.view.ContextMenu.ContextMenuInfo import android.widget.ImageView import android.widget.ImageView.ScaleType import android.widget.LinearLayout import android.widget.TextView import android.widget.Toast import io.shentuzhigang.demo.shopping.MainApplication import io.shentuzhigang.demo.shopping.bean.CartInfo import io.shentuzhigang.demo.shopping.bean.GoodsInfo import io.shentuzhigang.demo.shopping.database.CartDBHelper import io.shentuzhigang.demo.shopping.database.GoodsDBHelper import io.shentuzhigang.demo.shopping.util.FileUtil import io.shentuzhigang.demo.shopping.util.SharedUtil import java.util.*/*** Created by ouyangshen on 2017/10/1.*/ @SuppressLint("SetTextI18n") class ShoppingCartActivity : Activity(), View.OnClickListener {private lateinit var iv_menu: ImageViewprivate lateinit var tv_count: TextViewprivate lateinit var tv_total_price: TextViewprivate lateinit var ll_content: LinearLayoutprivate lateinit var ll_cart: LinearLayoutprivate lateinit var ll_empty: LinearLayoutprivate var mCount // 購(gòu)物車中的商品數(shù)量= 0private var mGoodsHelper // 聲明一個(gè)商品數(shù)據(jù)庫(kù)的幫助器對(duì)象: GoodsDBHelper? = nullprivate var mCartHelper // 聲明一個(gè)購(gòu)物車數(shù)據(jù)庫(kù)的幫助器對(duì)象: CartDBHelper? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)requestWindowFeature(Window.FEATURE_NO_TITLE)setContentView(R.layout.activity_shopping_cart)iv_menu = findViewById(R.id.iv_menu)val tv_title = findViewById<TextView>(R.id.tv_title)tv_count = findViewById(R.id.tv_count)tv_total_price = findViewById(R.id.tv_total_price)ll_content = findViewById(R.id.ll_content)ll_cart = findViewById(R.id.ll_cart)ll_empty = findViewById(R.id.ll_empty)iv_menu.setOnClickListener(this)findViewById<View>(R.id.btn_shopping_channel).setOnClickListener(this)findViewById<View>(R.id.btn_settle).setOnClickListener(this)iv_menu.setVisibility(View.VISIBLE)tv_title.text = "購(gòu)物車"}// 顯示購(gòu)物車圖標(biāo)中的商品數(shù)量private fun showCount(count: Int) {mCount = counttv_count!!.text = "" + mCountif (mCount == 0) {ll_content!!.visibility = View.GONEll_cart!!.removeAllViews()ll_empty!!.visibility = View.VISIBLE} else {ll_content!!.visibility = View.VISIBLEll_empty!!.visibility = View.GONE}}override fun onClick(v: View) {if (v.id == R.id.iv_menu) { // 點(diǎn)擊了菜單圖標(biāo)openOptionsMenu()} else if (v.id == R.id.btn_shopping_channel) { // 點(diǎn)擊了“商場(chǎng)”按鈕// 跳轉(zhuǎn)到手機(jī)商場(chǎng)頁(yè)面val intent = Intent(this, ShoppingChannelActivity::class.java)startActivity(intent)} else if (v.id == R.id.btn_settle) { // 點(diǎn)擊了“結(jié)算”按鈕val builder = AlertDialog.Builder(this)builder.setTitle("結(jié)算商品")builder.setMessage("客官抱歉,支付功能尚未開通,請(qǐng)下次再來(lái)")builder.setPositiveButton("我知道了", null)builder.create().show()}}override fun onCreateOptionsMenu(menu: Menu): Boolean {// 從menu_cart.xml中構(gòu)建菜單界面布局menuInflater.inflate(R.menu.menu_cart, menu)return true}override fun onOptionsItemSelected(item: MenuItem): Boolean {val id = item.itemIdif (id == R.id.menu_shopping) { // 點(diǎn)擊了菜單項(xiàng)“去商場(chǎng)購(gòu)物”// 跳轉(zhuǎn)到商場(chǎng)頁(yè)面val intent = Intent(this, ShoppingChannelActivity::class.java)startActivity(intent)} else if (id == R.id.menu_clear) { // 點(diǎn)擊了菜單項(xiàng)“清空購(gòu)物車”// 清空購(gòu)物車數(shù)據(jù)庫(kù)mCartHelper!!.deleteAll()ll_cart!!.removeAllViews()// 把最新的商品數(shù)量寫入共享參數(shù)SharedUtil.Companion.getIntance(this)!!.writeShared("count", "0")// 顯示最新的商品數(shù)量showCount(0)mCartGoods.clear()mGoodsMap.clear()Toast.makeText(this, "購(gòu)物車已清空", Toast.LENGTH_SHORT).show()} else if (id == R.id.menu_return) { // 點(diǎn)擊了菜單項(xiàng)“返回”finish()}return true}// 聲明一個(gè)根據(jù)視圖編號(hào)查找商品信息的映射private val mCartGoods: HashMap<Int, CartInfo> = HashMap<Int, CartInfo>()// 聲明一個(gè)觸發(fā)上下文菜單的視圖對(duì)象private var mContextView: View? = nulloverride fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenuInfo) {// 保存該商品行的視圖,以便刪除商品時(shí)一塊從列表移除該行mContextView = v// 從menu_goods.xml中構(gòu)建菜單界面布局menuInflater.inflate(R.menu.menu_goods, menu)}override fun onContextItemSelected(item: MenuItem): Boolean {val info: CartInfo? = mCartGoods[mContextView!!.id]val id = item.itemIdif (id == R.id.menu_detail) { // 點(diǎn)擊了菜單項(xiàng)“查看商品詳情”// 跳轉(zhuǎn)到查看商品詳情頁(yè)面goDetail(info!!.goods_id)} else if (id == R.id.menu_delete) { // 點(diǎn)擊了菜單項(xiàng)“從購(gòu)物車刪除”val goods_id: Long = info!!.goods_id// 從購(gòu)物車刪除商品的數(shù)據(jù)庫(kù)操作mCartHelper!!.delete("goods_id=$goods_id")// 從購(gòu)物車列表中刪除該商品行ll_cart!!.removeView(mContextView)// 更新購(gòu)物車中的商品數(shù)量var left_count: Int = mCount - info!!.countfor (i in mCartArray!!.indices) {if (goods_id == mCartArray!![i].goods_id) {left_count = mCount - mCartArray!![i].countmCartArray!!.removeAt(i)break}}// 把最新的商品數(shù)量寫入共享參數(shù)SharedUtil.Companion.getIntance(this)!!.writeShared("count", "" + left_count)// 顯示最新的商品數(shù)量showCount(left_count)Toast.makeText(this, "已從購(gòu)物車刪除" + mGoodsMap[goods_id]!!.name, Toast.LENGTH_SHORT).show()mGoodsMap.remove(goods_id)refreshTotalPrice()}return true}// 跳轉(zhuǎn)到商品詳情頁(yè)面private fun goDetail(rowid: Long) {val intent = Intent(this, ShoppingDetailActivity::class.java)intent.putExtra("goods_id", rowid)startActivity(intent)}override fun onResume() {super.onResume()// 獲取共享參數(shù)保存的購(gòu)物車中的商品數(shù)量mCount = SharedUtil.Companion.getIntance(this)!!.readShared("count", "0")!!.toInt()showCount(mCount)// 獲取商品數(shù)據(jù)庫(kù)的幫助器對(duì)象mGoodsHelper = GoodsDBHelper.Companion.getInstance(this, 1)// 打開商品數(shù)據(jù)庫(kù)的寫連接mGoodsHelper!!.openWriteLink()// 獲取購(gòu)物車數(shù)據(jù)庫(kù)的幫助器對(duì)象mCartHelper = CartDBHelper.Companion.getInstance(this, 1)// 打開購(gòu)物車數(shù)據(jù)庫(kù)的寫連接mCartHelper!!.openWriteLink()// 模擬從網(wǎng)絡(luò)下載商品圖片downloadGoods()// 展示購(gòu)物車中的商品列表showCart()}override fun onPause() {super.onPause()// 關(guān)閉商品數(shù)據(jù)庫(kù)的數(shù)據(jù)庫(kù)連接mGoodsHelper!!.closeLink()// 關(guān)閉購(gòu)物車數(shù)據(jù)庫(kù)的數(shù)據(jù)庫(kù)連接mCartHelper!!.closeLink()}// 聲明一個(gè)起始的視圖編號(hào)private val mBeginViewId = 0x7F24FFF0// 聲明一個(gè)購(gòu)物車中的商品信息隊(duì)列private var mCartArray: ArrayList<CartInfo>? = ArrayList<CartInfo>()// 聲明一個(gè)根據(jù)商品編號(hào)查找商品信息的映射private val mGoodsMap: HashMap<Long, GoodsInfo?> = HashMap<Long, GoodsInfo?>()// 展示購(gòu)物車中的商品列表private fun showCart() {// 查詢購(gòu)物車數(shù)據(jù)庫(kù)中所有的商品記錄mCartArray = mCartHelper!!.query("1=1")Log.d(TAG, "mCartArray.size()=" + mCartArray!!.size)if (mCartArray == null || mCartArray!!.size <= 0) {return}// 移除線性視圖ll_cart下面的所有子視圖ll_cart.removeAllViews()// 創(chuàng)建一個(gè)標(biāo)題行的線性視圖ll_rowvar ll_row = newLinearLayout(LinearLayout.HORIZONTAL, ViewGroup.LayoutParams.WRAP_CONTENT)ll_row.addView(newTextView(0, 2f, Gravity.CENTER, "圖片", Color.BLACK, 15))ll_row.addView(newTextView(0, 3f, Gravity.CENTER, "名稱", Color.BLACK, 15))ll_row.addView(newTextView(0, 1f, Gravity.CENTER, "數(shù)量", Color.BLACK, 15))ll_row.addView(newTextView(0, 1f, Gravity.CENTER, "單價(jià)", Color.BLACK, 15))ll_row.addView(newTextView(0, 1f, Gravity.CENTER, "總價(jià)", Color.BLACK, 15))// 把標(biāo)題行添加到購(gòu)物車列表ll_cart.addView(ll_row)for (i in mCartArray!!.indices) {val info: CartInfo = mCartArray!![i]// 根據(jù)商品編號(hào)查詢商品數(shù)據(jù)庫(kù)中的商品記錄val goods: GoodsInfo? = mGoodsHelper!!.queryById(info.goods_id)Log.d(TAG, "name=" + goods!!.name + ",price=" + goods.price + ",desc=" + goods.desc)mGoodsMap[info.goods_id] = goods// 創(chuàng)建該商品行的水平線性視圖,從左到右依次為商品小圖、商品名稱與描述、商品數(shù)量、商品單價(jià)、商品總價(jià)。ll_row = newLinearLayout(LinearLayout.HORIZONTAL, ViewGroup.LayoutParams.WRAP_CONTENT)// 設(shè)置該線性視圖的編號(hào)ll_row.id = mBeginViewId + i// 添加商品小圖val iv_thumb = ImageView(this)val iv_params = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 2F)iv_thumb.layoutParams = iv_paramsiv_thumb.scaleType = ScaleType.FIT_CENTERiv_thumb.setImageBitmap(MainApplication.instance?.mIconMap?.get(info.goods_id))ll_row.addView(iv_thumb)// 添加商品名稱與描述val ll_name = LinearLayout(this)val params = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 3F)ll_name.layoutParams = paramsll_name.orientation = LinearLayout.VERTICALll_name.addView(newTextView(-3, 1f, Gravity.LEFT, goods.name, Color.BLACK, 17))ll_name.addView(newTextView(-3, 1f, Gravity.LEFT, goods.desc, Color.GRAY, 12))ll_row.addView(ll_name)// 添加商品數(shù)量、單價(jià)和總價(jià)ll_row.addView(newTextView(1, 1f, Gravity.CENTER, "" + info.count, Color.BLACK, 17))ll_row.addView(newTextView(1,1f,Gravity.RIGHT,"" + goods.price.toInt(),Color.BLACK,15))ll_row.addView(newTextView(1,1f,Gravity.RIGHT,"" + (info.count * goods.price).toInt(),Color.RED,17))// 給商品行添加點(diǎn)擊事件ll_row.setOnClickListener { goDetail(info.goods_id) }// 給商品行注冊(cè)上下文菜單,為防止重復(fù)注冊(cè),這里先注銷再注冊(cè)unregisterForContextMenu(ll_row)registerForContextMenu(ll_row)mCartGoods[ll_row.id] = info// 往購(gòu)物車列表添加該商品行ll_cart.addView(ll_row)}// 重新計(jì)算購(gòu)物車中的商品總金額refreshTotalPrice()}// 重新計(jì)算購(gòu)物車中的商品總金額private fun refreshTotalPrice() {var total_price = 0for (info in mCartArray!!) {val goods: GoodsInfo? = mGoodsMap[info.goods_id]total_price += (goods!!.price * info.count).toInt()}tv_total_price.text = "" + total_price}// 創(chuàng)建一個(gè)線性視圖的框架private fun newLinearLayout(orientation: Int, height: Int): LinearLayout {val ll_new = LinearLayout(this)val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height)ll_new.layoutParams = paramsll_new.orientation = orientationll_new.setBackgroundColor(Color.WHITE)return ll_new}// 創(chuàng)建一個(gè)文本視圖的模板private fun newTextView(height: Int,weight: Float,gravity: Int,text: String,textColor: Int,textSize: Int): TextView {val tv_new = TextView(this)if (height == -3) { // 垂直排列val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, weight)tv_new.layoutParams = params} else { // 水平排列val params = LinearLayout.LayoutParams(0,if (height == 0) ViewGroup.LayoutParams.WRAP_CONTENT else ViewGroup.LayoutParams.MATCH_PARENT,weight)tv_new.layoutParams = params}tv_new.text = texttv_new.setTextColor(textColor)tv_new.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize.toFloat())tv_new.gravity = Gravity.CENTER or gravityreturn tv_new}private var mFirst: String? = "true" // 是否首次打開// 模擬網(wǎng)絡(luò)數(shù)據(jù),初始化數(shù)據(jù)庫(kù)中的商品信息private fun downloadGoods() {// 獲取共享參數(shù)保存的是否首次打開參數(shù)mFirst = SharedUtil.Companion.getIntance(this)!!.readShared("first", "true")// 獲取當(dāng)前App的私有存儲(chǔ)路徑val path: String = MainApplication.instance?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString().toString() + "/"if (mFirst == "true") { // 如果是首次打開val goodsList: ArrayList<GoodsInfo> = GoodsInfo.defaultListfor (i in goodsList.indices) {val info: GoodsInfo = goodsList[i]// 往商品數(shù)據(jù)庫(kù)插入一條該商品的記錄val rowid: Long = mGoodsHelper!!.insert(info)info.rowid = rowid// 往全局內(nèi)存寫入商品小圖val thumb = BitmapFactory.decodeResource(resources, info.thumb)MainApplication.instance?.mIconMap?.put(rowid, thumb)val thumb_path = path + rowid + "_s.jpg"FileUtil.saveImage(thumb_path, thumb)info.thumb_path = thumb_path// 往SD卡保存商品大圖val pic = BitmapFactory.decodeResource(resources, info.pic)val pic_path = "$path$rowid.jpg"FileUtil.saveImage(pic_path, pic)pic.recycle()info.pic_path = pic_path// 更新商品數(shù)據(jù)庫(kù)中該商品記錄的圖片路徑mGoodsHelper!!.update(info)}} else { // 不是首次打開// 查詢商品數(shù)據(jù)庫(kù)中所有商品記錄val goodsArray: ArrayList<GoodsInfo> = mGoodsHelper!!.query("1=1")for (i in goodsArray.indices) {val info: GoodsInfo = goodsArray[i]// 從指定路徑讀取圖片文件的位圖數(shù)據(jù)val thumb = BitmapFactory.decodeFile(info.thumb_path)// 把該位圖對(duì)象保存到應(yīng)用實(shí)例的全局變量中MainApplication.instance?.mIconMap?.put(info.rowid, thumb)}}// 把是否首次打開寫入共享參數(shù)SharedUtil.Companion.getIntance(this)!!.writeShared("first", "false")}companion object {private const val TAG = "ShoppingCartActivity"} }實(shí)驗(yàn)結(jié)果(實(shí)驗(yàn)最終作品截圖說(shuō)明)
實(shí)驗(yàn)心得
1、熟悉Android五種主要存儲(chǔ)方式的用法,包括共享參數(shù)SharedPreferences、數(shù)據(jù)庫(kù)SQLite、SD卡文件、App的全局內(nèi)存;
2、熟悉重要組件之一的應(yīng)用Application的基本概念與常見用法,以及四大組件之一的內(nèi)容提供器ContentProvider的基本概念與常見用法;
參考文章
總結(jié)
以上是生活随笔為你收集整理的《移动项目实践》实验报告——Android数据存储的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android11——DataBindi
- 下一篇: 《移动项目实践》实验报告——Androi