1.引言
在这个科技与网络齐头并进的时代,外卖服务正在飞速发展,人们对外卖APP系统功能需求越来越多,开发APP的人员对自己的要求也要越来越高,要从所做APP外卖系统所实现的功能和用户的需求来对系统进行设计,还需要与当下所飞速发展的网络相结合来设计,让用户使用方便。所以在当今网络快速发展的环境下开发一个专为农民售卖蔬菜水果的APP会有很好的发展空间,而且如今外卖APP层出不穷,市面上的外卖APP加上小程序内的就已经上千不止,大型的外卖APP在全国的范围内大约有1亿多人在使用,年轻人占比超过50%,年轻人是最活跃的群体。在学校内也有着各种外卖小程序,经过一段时间的调查,使用率也是非常高,几乎每个学生都使用过。所以开发一个蔬菜类的外卖APP,很多人都会很快上手,即使是老年人,通过让自己的子女教学之后,也可以很快上手,而使用简单又功能齐全这也是对开发生鲜蔬APP的一种挑战。
整个APP系统主要功能的实现和后期系统的维护,需要结合用户的实际需求来设计出一个专门售卖蔬菜的APP。此APP系统的设计需要满足操作简单的特点。在如今网络快速发展的当下,网络带来的便捷被很多人喜欢,例如现在市场上存在的外卖APP,人们使用的越来越多,发展前景非常好。而且生鲜蔬APP的开发还可以让很多无业的人去进行配送,可以解决一部分就业问题,商家可以选择自己配送,雇人配送。利用本APP系统解决了最初目的以外的就业问题。所以,对于这个生鲜蔬APP外卖系统来说,它非常符合需求,很符合当下网络快速发展的世界。
2.开发技术
2.1 Java语言
Java语言由Sun发布。具有公开源码的优点。这一优点让世界各地的编程爱好者对其产生了很大的兴趣。Java语言具有很多特性,与其它语言有很大的不同,具体如下:
(1)平台无关:在编写出代码之后,不止可以运行在编写时所用的平台上面,即使切换到其他平台,只要在新的系统中下载官网的编译环境,就可以同样执行。
(2)面向对象:面向对象的解决问题思路相比于面向过程,它在编写代码初期可能会麻烦但是在后期效率会成倍的提升。
(3)源代码开源:在编写Java程序的时候,有时会用到一些比较深的代码,就可以直接去查看源码,再去官网寻找相应的中文解释,就可以很好地理解原理,对其进行使用。
(4)代码简单:学习Java语言,只要你自己系统的学习过一门语言,再学习的时候,就会很快的上手,其编写格式大致相同。即使没有学习过,对比其他语言来说,也是可以相对很快的上手。
其中面向对象,可以很方便的帮助们解决一些生活中的实际问题[2]。跨平台性也很实用。在各个操作系统中都可以运行。Java技术它还是一门容易让人学会和使用的一门服务器语言,可以使用它去链接市面上大部分的服务器进行后台的编写。
2.2 Node.js和JavaScript
Node.js不是编程语言,是一个平台,Node.js让JavaScript出现在后端成为了可能,可以在服务端单独执行。它的学习曲线非常简单,经过简单的学习就可以入门,对其进行简单使用。
JavaScript不是编程语言,是脚本语言,是web开发人员使用最多的语言之一它需要一个运行环境。在Node.js出现之前,JavaScript只可以在浏览器上面运行,Node.js出现之后多了一个新的可以运行的环境,Node.js平台。
2.3 SQLite数据库
SQLite不仅具有嵌入式特点还有轻型的特点。占用空间少。在很多主流的系统中都可以进行使用,还可以与很多的语言进行结合。由于拥有占用内存小的优点,处理速度也比一般的数据库系统快,与之相对应的是,不可以进行大量数据的存储。
3.功能设计
3.1 总体设计思想
本系统起初开发目标是为售卖蔬菜不方便的农户开发一个专用APP来进行售卖,并且要易于他们的使用,经过分析之后,不仅可以对蔬菜等进行售卖,还可以对水果等等,农产品。通过本APP农户们可以不用每天带着自己的菜品去集市去售卖,只需在家里就可以进行售卖。
本APP系统设计是从数据分析开始的,分析完成之后进行具体的代码编写,从一个登录界面的布局开始,然后是注册界面,APP主界面,商品列表界面,个人中心界面,将这些界面代码分成各个布局文件装在layout文件夹中。对其中需要用到的图片等信息在网络上进行搜集,导入drawable中,然后在Activity文件夹中,先定义一些各个布局文件的变量,再对各个布局文件进行获取。对于店铺信息和商品信息则是,通过后天的Node.js运行所编写的js代码,在dos命令窗口执行对应的文件,在Java代码内对其中的内容进行获取,最后导入到相应的布局文件。然后对模块进行相应功能的编写,然后将各个独立的页面再进行声明,连接在一起,最后将整个程序的入口代码,写在登录界面的代码中,就可以将各个模块连接在一起,形成一个完整的APP系统。
3.2 功能模块结构图
(1)用户登录:点击APP图标进入登录界面,没有账号的话,可以进行注册,还有记住密码,自动登录的功能。
(2)店铺页面以及个人中心:登录成功之后可以看到正在售卖的货品的店铺,还可以点击个人中心图标,修改个人信息。
(3)货品列表和详情:点击列表中的店铺可以看到店铺内正在出售的商品,可以对店铺内中意的货品进行购买,点击相应的货品会看到商品详情。
(4)购物车以及进行支付:点击购买之后会自动放入购物车,挑选完成之后进行支付结算系统结构如图。
4.功能效果图
4.1 登录界面
点击图标进入登录界面,可以通过点击登陆下方的文字,注册之后点击返回进行登录,登录之后可以看到正在出售商品的店铺列表,如图所示。
4.2 系统主界面
用户进入APP,登录成功之后,可以直观看到正在售卖的菜品以及水果的店铺,挑选自己心仪的店铺,如图所示。
4.3 商品列表界面
点击所想进入的店铺之后,会看到店铺内正在出售的菜品以及水果,然后对其进行添加购物车,点击所想买的商品之后,会出来商品的详情介绍,介绍商品的具体信息,如图所示。
4.4 购物车界面
把需要的商品添加到购物车,接着输入收货地址,然后进行支付,修改等选择,点击支付会弹出一个支付窗口显示出对应店铺的收款码,如图所示。
4.5 个人中心及修改界面
个人中心可以显示头像,账号,出生日期,个人签名,常用地址,点击编辑资料,您可以更改帐号以外的信息,如图所示。
5.核心代码
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "com.example.biyesheji";
public static final String BUILD_TYPE = "debug";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
}
public class MainActivity extends AppCompatActivity {
private RelativeLayout rlTitleBar;
private TextView tvTitle;
private ListView lvShopList;
private ShopAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
private void initView(){
rlTitleBar = findViewById(R.id.rl_title_bar);
tvTitle=findViewById(R.id.tv_title);
lvShopList=findViewById(R.id.lv_shop_list);
adapter =new ShopAdapter(this);
lvShopList.setAdapter(adapter);
tvTitle.setText("店铺");
rlTitleBar.setBackgroundColor(getResources().getColor(R.color.blue_color));
}
private void initData(){
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder().url(Constants.WEB_SITE+Constants.REQUEST_SHOP_DATA).build();
Call call=client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String json=response.body().string();
Log.d("mzxy","json"+json);
List<ShopBean> list= JsonParse.getInstance().getShopList(json);
runOnUiThread(new Runnable() {
@Override
public void run() {
adapter.setData(list);
}
});
}
});
}
}
public class ShopDetailAcitivity extends AppCompatActivity implements View.OnClickListener {
private TextView tvShopName,tvTime,tvNotice,tvTile;
private ImageView ivShopPic,ivBack;
private ShopBean bean;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//绑定布局文件,把布局文件当作我们这个activity的界面
setContentView(R.layout.acitivity_shop_detail);
bean= (ShopBean) getIntent().getSerializableExtra("shop");
if(bean==null){
return;
}
initView();
setData();
}
private void setData() {
tvShopName.setText(bean.getShopName());
tvTime.setText(bean.getTime());
tvNotice.setText(bean.getShopNotice());
Glide.with(this).load(bean.getShopPic()).error(R.mipmap.ic_launcher).into(ivShopPic);
}
private void initView() {
tvShopName=findViewById(R.id.tv_shop_name);
tvTime=findViewById(R.id.tv_time);
tvNotice=findViewById(R.id.tv_notice);
tvTile=findViewById(R.id.tv_title);
ivShopPic=findViewById(R.id.iv_shop_pic);
ivBack=findViewById(R.id.iv_back);
tvTile.setText("店铺详情");
ivBack.setVisibility(View.VISIBLE);
ivBack.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.iv_back:
finish();
break;
}
}
}
public class ShopAdapter extends BaseAdapter {
private Context context;
private List<ShopBean> data=new ArrayList<>();
public ShopAdapter(Context context) {
this.context = context;
}
public void setData(List<ShopBean> data) {
this.data.clear();
this.data.addAll(data); //我们不能改变this.data的地址,否则会导致无法刷新数据
// 数据有变化,要让我们的数据进行刷新
notifyDataSetChanged();
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder=null;
if(convertView==null){
convertView= LayoutInflater.from(context).inflate(R.layout.shop_item,null);
viewHolder=new ViewHolder();
viewHolder.tvOfferPrice=convertView.findViewById(R.id.tv_offer_price);
viewHolder.tvShopName=convertView.findViewById(R.id.tv_shop_name);
viewHolder.tvSaleNum=convertView.findViewById(R.id.tv_sale_num);
viewHolder.tvWelfare=convertView.findViewById(R.id.tv_welfare);
viewHolder.tvTime=convertView.findViewById(R.id.tv_time);
viewHolder.ivShopPic=convertView.findViewById(R.id.iv_shop_pic);
convertView.setTag(viewHolder);
}else{
viewHolder=(ViewHolder) convertView.getTag();
}
ShopBean shopBean=data.get(position);
Glide.with(context).load(shopBean.getShopPic()).error(R.mipmap.ic_launcher).into(viewHolder.ivShopPic);
viewHolder.tvTime.setText(shopBean.getTime());
viewHolder.tvWelfare.setText(shopBean.getWelfare());
viewHolder.tvSaleNum.setText("月售"+shopBean.getSaleNum());
viewHolder.tvShopName.setText(shopBean.getShopName());
viewHolder.tvOfferPrice.setText("起送"+shopBean.getOfferPrice()+"元,配送"+shopBean.getDistributionCost()+"元");
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(context, ShopDetailAcitivity.class);
intent.putExtra("shop",shopBean);
context.startActivity(intent);
}
});
return convertView;
}
class ViewHolder{
TextView tvShopName,tvSaleNum,tvOfferPrice,tvWelfare,tvTime;
ImageView ivShopPic;
}
}
public class FoodBean implements Serializable{
private String foodId;
private String foodName;
private String taste;
private String saleNum;
private BigDecimal price;
private int count;
private String foodPic;
public String getFoodId() {
return foodId;
}
public void setFoodId(String foodId) {
this.foodId = foodId;
}
public String getFoodName() {
return foodName;
}
public void setFoodName(String foodName) {
this.foodName = foodName;
}
public String getTaste() {
return taste;
}
public void setTaste(String taste) {
this.taste = taste;
}
public String getSaleNum() {
return saleNum;
}
public void setSaleNum(String saleNum) {
this.saleNum = saleNum;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public String getFoodPic() {
return foodPic;
}
public void setFoodPic(String foodPic) {
this.foodPic = foodPic;
}
}
public class ShopBean implements Serializable {
private Integer id;
private String shopName;
private int saleNum;
private BigDecimal offerPrice;
private int distributionCost;
private String welfare;
private String time;
private String shopPic;
private String shopNotice;
private List<FoodBean> foodList;
public List<FoodBean> getFoodList() {
return foodList;
}
public void setFoodList(List<FoodBean> foodList) {
this.foodList = foodList;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getShopName() {
return shopName;
}
public void setShopName(String shopName) {
this.shopName = shopName;
}
public Integer getSaleNum() {
return saleNum;
}
public void setSaleNum(Integer saleNum) {
this.saleNum = saleNum;
}
public BigDecimal
getOfferPrice() {
return offerPrice;
}
public void setOfferPrice(BigDecimal offerPrice) {
this.offerPrice = offerPrice;
}
public Integer getDistributionCost() {
return distributionCost;
}
public void setDistributionCost(Integer distributionCost) {
this.distributionCost = distributionCost;
}
public String getWelfare() {
return welfare;
}
public void setWelfare(String welfare) {
this.welfare = welfare;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getShopPic() {
return shopPic;
}
public void setShopPic(String shopPic) {
this.shopPic = shopPic;
}
public String getShopNotice() {
return shopNotice;
}
public void setShopNotice(String shopNotice) {
this.shopNotice = shopNotice;
}
}
public class ShopListView extends ListView {
public ShopListView(Context context) {
super(context);
}
public ShopListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ShopListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightSpec=MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE>>2,MeasureSpec.AT_MOST); //view是用30位进行存储,那么我们应该给他30位的最大值,Int的最大值是32位,
super.onMeasure(widthMeasureSpec, heightSpec);
}
}
6.参考论文
目录
1引言
1.1课题背景
1.2研究现状
1.3研究内容
2开发环境
2.1 Java语言介绍
2.2 Node.js与JavaScript介绍
2.3 SQLite数据库介绍
3系统分析
3.1可行性分析
3.1.1经济可行性
3.1.2技术可行性
3.1.3操作可行性
3.2 性能需求分析
3.3设计流程分析
4系统设计
4.1系统总体设计思想
4.2系统功能模块结构图以及介绍
4.3数据库设计
5系统功能实现
5.1登陆界面
5.2系统主界面
5.3商品列表界面
5.4购物车界面
5.5个人中心以及修改资料界面
6 APP测试
6.1程序测试
6.2测试具体分析
6.3测试结论
6.4 APP后续展望
结论
参考文献
7.总结
生鲜蔬APP系统的实现过程中,最常用的技术是Java,JavaScript语言,数据库是带SQList数据库的Android Studio,服务端使用的是Node.js。在测试完成并进行相应不足之处的修改之后,生鲜蔬APP可以完美地运行。用户通过注册帐号之后返回登录界面,登录进入APP之后对自己所需要的商品添加购物车,然后支付。
在整个生鲜蔬APP开发过程中,大部分内容是自己完成,在遇到问题的时候去请教了同学,和在网上查阅相关资料和例子。最终完成了生鲜蔬APP的设计,整个开发过程让收获了许多有用的东西。
在此之前对于的APP并没有进行过什么深度理解,所以在一开始遇到了一些难题,例如购物车就是在整个研发过程当中所面临的最大问题,一开始实现时只是完成了界面,但对于添加或者删除的功能却存在着很多的问题,这个问题是一大难题,其中涉及到算法,界面交互等,但最终通过同学和查阅网上资料解决了。在解决这个最大的问题之后,心里感觉很开心,增加了自信,在以后遇到难题的时候有信心去克服。在完成毕业设计的过程中学到了,在书本上学到的东西是远远不够的。要想真正的从事这一行业,就必须多上手实操付诸实践。经过在实践中的磨练,才可以真正懂得理论,才会真正的掌握书本上的知识。经历毕业设计过后,发觉自己学到不只有专业知识,还有将实践与理论相结合的方法,在这整个的设计过程中,其中更多的是遇到困难永不后退的态度。