日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android学习之网上商城(上)

發布時間:2025/3/15 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android学习之网上商城(上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

又到了課設的時候,這次課設比較難受,因為兩周時間中還有3門考試,在課設的時候還要復習,著實耗費了不少的精力,不過也收獲多多,接下來總結一下本次課設中學到的東西

Android學習之網上商城(上)
Android學習之網上商城(下)

源碼下載:
鏈接:https://pan.baidu.com/s/1Z17xBHV9iq70LwdgXxwDIQ
提取碼:Lin2

Android學習之網上商城源代碼

本博客內容原創,創作不易,轉載請注明

本文鏈接

個人博客:https://ronglin.fun/?p=118
PDF鏈接:見博客網站
CSDN: https://blog.csdn.net/RongLin02/article/details/121876257

開發環境:

  • Android Studio版本:(Android Studio Arctic Fox 2020.3.1 Patch 3)
  • SDK版本:(Android 7.0 API24 Revision 2)
  • Gradle版本:(7.0.2)
  • Android Gradle Plugin版本:(7.0.3)

選題

題目

本次選題為網上商城/外賣小助手。要求如下:
功能要求

  • 要求實現商品展示、商品詳細介紹、下訂單、購物車。
  • 要求實現用戶注冊、登錄、查看歷時訂單。
  • 數據:可以采用靜態的固定的數據來模擬(如果動手能力較強,可以嘗試自己動手搭后臺,利用 Android 網絡編程)。

目的:

  • 掌握 Android 中的菜單及導航框架。
  • 掌握自定義布局。
  • 掌握 Android 中的數據存儲。

分析

1. 商品展示
商品展示準備用一個ListView展示內容,主要包括商品的名稱、價格、預覽圖、加入購物車功能等
2. 商品詳細介紹
這個界面準備用一個自定義Dialog實現,主要是布局設計,展示商品的名稱、價格、預覽圖、描述、標簽等
3. 購物車
購物車用一個ListView維護,主要是用來顯示用戶的購物車內容,這個界面的主要功能就是對購物車中的商品刪除和下單扣費,因為是靜態數據,準備用ArrayList數組維護
4. 下訂單
暫定實現用戶的扣費和將訂單加入歷史訂單中,用ArrayList維護,主要是內容的增加和刪除
5. 注冊
用單獨的一個Activity實現,主要是用于用戶的注冊,有三個數據,第一個是用戶名,第二個是密碼,第三個是確認密碼,然后注冊成功之后將數據插入本地數據庫,用戶列表主要用SQLite存儲。
6. 登錄
登錄就是比對用戶輸入和數據庫中的數據是否匹配,匹配則登錄成功,失敗則提示
7. 歷史訂單
歷史訂單用SQLite存儲,主要記錄的是用戶的用戶名,商品名稱和購物時間
8. 數據
由于時間有限,本次Android設計主要是用靜態數據,商品數據由本地寫死,用戶信息用SQLite數據庫維護

效果展示

注冊登錄

實現賬號的注冊與登錄,當用戶注冊完成后,會將注冊好的賬號密碼自動填入登錄界面中

商品展示

商品的展示界面,點擊每一行展示商品的詳細信息,點擊+號可以將商品添加到購物車中

購物車

購物車中需要扣費,在個人中心可以充值,然后購物的時候可以扣費

用法

這個模塊主要用來說明,在本次安卓開發用主要用的部分,一個ListView,一個是viewBinding,一個是Fragment,還有一些其他的用法

ListView

ListView是這其中最常用的控件,包括商品展示,購物車列表展示,個人中心中的歷史清單列表,都是用的ListView顯示數據。

item

在ListView中,每一行都是一個item,所以說要用ListView首先就是先設計一個item的布局文件,如下圖

部分代碼如下:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><ImageViewandroid:id="@+id/imageViewPreview"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"app:srcCompat="@drawable/default_goods"android:background="@color/white"android:adjustViewBounds="true"android:scaleType="centerInside"/><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"android:orientation="vertical">......</LinearLayout> </LinearLayout>

這樣新建一個item,并且為其中每一個按鈕設置好id

BaseAdapter

設計完每一行的顯示之后還不行,還要用代碼來設計每一個item是如何顯示的,這里就用到了Adapter適配器,因為我的數據顯示比較復雜,只能用自定義的適配器,定義一個類,繼承自BaseAdapter類,然后實現其中的幾個抽象方法,如下

package com.ronglin.linshopping.application;public class GoodsListAdapter extends BaseAdapter{private ArrayList<Goods> list_goods;public GoodsListAdapter(ArrayList<Goods> list, Context context){this.list_goods = list;this.context = context;}public void setListGoods(ArrayList<Goods> list){this.list_goods = list;}@Overridepublic int getCount() {return list_goods.size();}@Overridepublic Object getItem(int i) {return list_goods.get(i);}@Overridepublic long getItemId(int i) {return i;}@Overridepublic View getView(int i, View view, ViewGroup viewGroup) {View item_view;item_view = View.inflate(this.context, R.layout.list_item_goods,null);//設置列表的顯示形式TextView textViewGoodsName = item_view.findViewById(R.id.textViewGoodsName);textViewGoodsName.setText(list_goods.get(i).getGoodsName());return item_view;} }

這個GoodsListAdapter類就是用來控制每一行如何顯示的,為了實現動態數據,用了一個ArrayList實現數據存儲,然后顯示的數據都從ArrayList中提取這幾個方法簡單提示一下
getCount()用來獲取到底有多少行
getItem(int i)用來獲取第i行(從0開始)的數據類
getItemId(int i)用來獲取第i行(從0開始)的數據id
getView(int i, View view, ViewGroup viewGroup)用來設置第i行(從0開始)的顯示形式

Bottom Navigation Activity

因為要實現多個界面切換,在設計時看到Android Studio中的Activity的時候,看到了Bottom Navigation Activity,是用底邊欄按鈕切換界面,下面簡單介紹一下它的用法

文件分布

bottom_nav_menu.xml
首先是/res/menu下的bottom_nav_menu.xml,這個文件的作用是控制底邊欄的樣式,比如購物車的圖標,名稱之類的,基本格式如下:

<itemandroid:id="@+id/navigation_person"android:icon="@drawable/person"android:title="@string/title_person" />

文件中主要就是item,根據所查的資料,item的個數是3–5個,icon就是底邊欄的按鈕圖標,title就是底邊欄的名稱

mobile_navigation.xml
然后就是在/res/navigation下的mobile_navigation.xml,這個文件就是設置每一個item中面板內容,基本內容如下

<fragmentandroid:id="@+id/navigation_goods"android:name="com.ronglin.linshopping.ui.goods.GoodsFragment"android:label="@string/title_goods"tools:layout="@layout/fragment_goods" />

android:name 是用來配置控制界面的類,格式是包名.類名
tools:layout 是用來設置每一個界面的布局文件

簡單使用

切換界面
如果想要切換手動的切換界面,要這樣使用

binding.imageButtonShopping.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Navigation.findNavController(GoodsFragment.this.getView()).navigate(R.id.navigation_shopping);}});

這句代碼的作用就是切換界面
然后就是Fragment的用法,關于Fragment下面還有用法說明

viewBinding

因為我用的是系統自動生成的Bottom Navigation Activity(底邊欄按鈕切換界面),在自動生成的代碼中,用到了viewBinding,查了一下資料,發現用起來很方便,這里簡單的說一下使用

build.gradle

首先要是想使用viewBinding,要在build.gradle(Module:xxx)中開啟viewBinding

android {compileSdk 30......buildFeatures {viewBinding true} }

然后就可以用了

使用說明

開啟viewBinding后,它會把每一個layout目錄下的 xml 文件按照 駝峰命名法 生成了一個類,例如activity_main.xml文件就被生成類ActivityMainBinding然后就可以通過類的實例來訪問其中的控件
例如在test_layout.xml中如下定義

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="45dp"><EditTextandroid:id="@+id/editTextSearch"android:gravity="center_vertical"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="4"android:layout_gravity="center_vertical"android:layout_margin="5dp"/> </LinearLayout>

然后在Activity中就可以這樣使用

public class MainActivity extends AppCompatActivity {private TestLayoutBinding binding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = TestLayoutBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());binding.editTextSearch.setText("test");} }

通過binding.Id名稱就可以訪問到特定的控件了,如果沒有在Activity中,只有Context對象的話,可以這樣初始化

binding = TestLayoutBinding.inflate(LayoutInflater.from(context));

之后就基本上可以不用findViewById方法了,就可以直接用binding來訪問控件了。
注意:
當和ListView中的BaseAdapter一起使用時,不能用binding,還是要用findViewById方法,不知道是不是自己用錯了,幾次嘗試之后都顯示失敗,無果后只能放棄

Fragment

在使用系統自動生成的Bottom Navigation Activity時,它生成了3個Fragment。
以下部分內容來官方API文檔
Fragment 表示應用界面中可重復使用的一部分。Fragment 定義和管理自己的布局,具有自己的生命周期,并且可以處理自己的輸入事件。Fragment 不能獨立存在,而是必須由 Activity 或另一個 Fragment 托管。Fragment 的視圖層次結構會成為宿主的視圖層次結構的一部分,或附加到宿主的視圖層次結構。

生命周期


這是它的生命周期圖,和Activity很像,簡單說明一下,Fragment不能夠單獨使用,要嵌套在Activity中使用,其生命周期也受到所在Activity的生命周期的影響,需要注意的是,在多個Fragment之中的切換,會調用onDestroyView和onCreateView同時數據會清空,但是對應的類并沒有被銷毀重構,只是界面View被銷毀重構

ViewModel

在使用Bottom Navigation Activity的時候,會發現,每一個界面類還會跟隨一個ViewModel類,這個類主要是用來存儲數據,用來適配Controller和Model之間的橋梁,同時用ViewModel也可以在多個Fragment中實現數據共享,接下來簡單的說明用法

初始化

private GoodsViewModel goodsViewModel;private FragmentGoodsBinding binding;public View onCreateView(@NonNull LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {binding = FragmentGoodsBinding.inflate(inflater, container, false);View root = binding.getRoot();goodsViewModel =new ViewModelProvider(this).get(GoodsViewModel.class);return root;}

可以看到ViewModel的初始化是在onCreateView中,所以說每當點擊切換Fragment的時候,ViewMode的數據都會重新初始化,這點要尤為注意

設置數據

先來簡單的看一下ViewModel類中的變量和方法

public class GoodsViewModel extends ViewModel {private final MutableLiveData<Goods> goods;public GoodsViewModel() {goods = new MutableLiveData<>();}public LiveData<Goods> getGoods() {return goods;}public void setGoods(Goods goods){this.goods.setValue(goods);} }

主要的變量就是一個MutableLiveData<?>類,這個類可以動態監聽值的變化,在對應的Fragment類中可以看到以下方法

goodsViewModel.getGoods().observe(getViewLifecycleOwner(), new Observer<Goods>() {@Overridepublic void onChanged(Goods goods) {Log.i("TAG",Goods.toString());}});

當類中Goods的值變化的時候就會自動執行onChanged的代碼,參數中的goods是變化之后的值
經過我的開發嘗試,只有在調用goodsViewModel.setGoods(goods)的時候才會被監聽到,所以說當用goodsViewModel.getGoods()方法獲取到數據之后,對數據的操作不會引起監聽變化,所以說當改變數據之后要調用一下goodsViewModel.setGoods()方法,如下:

goodsViewModel.getGoods().setPrice(1000); goodsViewModel.setGoods(goodsViewModel.getGoods());

這要變化之后就會調用監聽了

然后就是在其他的Fragment獲取數據

GoodsViewModel goodsViewModel; goodsViewModel = new ViewModelProvider(this).get(GoodsViewModel.class);

SQLite

在Android中,數據庫是使用SQLite的,關于SQLite用法網上有很多資料,這里簡單說一下用法

創建

數據庫的創建是需要創建一個類來繼承自SQLiteOpenHelper,然后在類中實現它的抽象方法,如下:

public class MySQLiteHelper extends SQLiteOpenHelper {public MySQLiteHelper(@Nullable Context context) {super(context,"LinShopping.db", null, 1);}@Overridepublic void onCreate(SQLiteDatabase sqLiteDatabase) {sqLiteDatabase.execSQL("create table person(username varchar(30) primary key,password varchar(30))");}@Overridepublic void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {} }

其中構造函數有很多,我這里只是實現了其中一個,主要是需要一個Context類來初始化,然后還要設置一下數據庫的名稱,這個數據庫的創建是在應用剛安裝的時候創建的,只會創建一次,然后在onCreate方法用來調用execSQL方法來創建新表

之后有關所有數據庫的操作都會用到這個SQLiteOpenHelper類

操作

我本人習慣將數據庫的操縱封裝成一個類來調用,所以說新建一個Database類來實現數據庫操作

public class Database {private MySQLiteHelper mySQLiteHelper;private SQLiteDatabase database;public Database(MySQLiteHelper mySQLiteHelper){this.mySQLiteHelper = mySQLiteHelper;} }

因為獲取數據庫需要用到SQLiteOpenHelper類,所以在構造函數中就需要傳入一個SQLiteOpenHelper類。
同時可以用execSQL方法直接輸入SQL語句操作數據,這里不再說明

增加方法比較簡單,如下

public void insertPersonToSQLite(Person person){database = mySQLiteHelper.getWritableDatabase();ContentValues values = new ContentValues();values.put("username",person.getUsername());values.put("password",person.getPassword());long id = database.insert("person",null,values);database.close();}

需要定義一個ContentValues類來保存Key-Value對,然后通過insert方法插入數據庫

刪除用法同樣比較簡單,如法如下:

public int deletePersonToSQLite(Person person){database = mySQLiteHelper.getWritableDatabase();int number = database.delete("person","username =?",new String[]{person.getUsername()});database.close();return number;}

用法如下

public int updatePersonToSQLite(Person person){database = mySQLiteHelper.getWritableDatabase();ContentValues values = new ContentValues();values.put("password",person.getPassword());int number = database.update("person",values,"username =?",new String[]{person.getUsername()});database.close();return number;}

查詢方法因為需要返回很多數據,所以說用法稍微麻煩一點點,實例如下:

public ArrayList<Person> findPersonFromSQLite(String username){database = mySQLiteHelper.getReadableDatabase();ArrayList<Person> list = new ArrayList<>();Cursor cursor = database.query("person",null,"username=?",new String[]{person.getUsername()},null,null,null);if (cursor.getCount() == 0){cursor.close();database.close();return list;} else {cursor.moveToFirst();list.add(new Person(cursor.getString(0),cursor.getString(1)));while (cursor.moveToNext()){list.add(new Person(cursor.getString(0),cursor.getString(1)));}cursor.close();database.close();return list;}}

簡單來說就是需要一個cursor游標來存儲返回的數據,然后通過操作游標來實現數據的獲取

其他功能

接下來是一些常用的小功能,用法

監聽文本框

有時候我們希望,我們的EditText只能輸入特定的內容或者當用戶輸入完畢后立刻處理結果,這樣就需要用到TextWatcher類了

binding.editTextSearch.addTextChangedListener(new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {String search = s.toString().trim();Log.i("TAG",search);}@Overridepublic void afterTextChanged(Editable editable) {} });

簡單的說明一下用法
beforeTextChanged(CharSequence s, int start, int count, int after)
s: 修改之前的文字。
start: 字符串中即將發生修改的位置。
count: 字符串中即將被修改的文字的長度。如果是新增的話則為0。
after: 被修改的文字修改之后的長度。如果是刪除的話則為0。

onTextChanged(CharSequence s, int start, int before, int count)
s: 改變后的字符串
start: 有變動的字符串的序號
before: 被改變的字符串長度,如果是新增則為0。
count: 添加的字符串長度,如果是刪除則為0。
afterTextChanged(Editable s)
s: 修改后的文字

修改機制如下:文字改變->watcher接收到通知->setText->文字改變->watcher接受到通知->…
參考:
Android TextWatcher內容監聽死循環
可以實現限制用戶輸入

@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {String search = s.toString().trim();Log.i("TAG",search);editTextSearch.removeTextChangedListener(this);editTextSearch.setText(search);editTextSearch.addTextChangedListener(this);}

定時器

因為Android中的UI界面是一個單線程,所以說如果要實現一個定時器,比如幾秒之后干什么,有點小困難,先看實例代碼

@SuppressLint("HandlerLeak") Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {//這里寫到時間之后的操作}};TimerTask task = new TimerTask(){public void run() {Message message = new Message();mHandler.sendMessage(message);}};Timer timer = new Timer();timer.schedule(task, 1000);

就是需要定義一個Handler類來處理消息,然后定義一個TimerTask類來發送消息,用一個Timer類來啟動

顯示圖片

圖片有很多類型,我這里用的是Bitmap類,從drawable目錄下構造Bitmap的方法如下:

Bitmap bitmap1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.renzituo));

用這個方法在生成release版本的時候,同樣會顯示,同時操作圖片也很方便.

總結

到此,一些本次課設中常用功能實現就總結完畢,接下來就是對單獨某些模塊的實現總結,未完待續,=w=

總結

以上是生活随笔為你收集整理的Android学习之网上商城(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。