“生鲜蔬”APP的设计与实现

简介: “生鲜蔬”APP的设计与实现

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并没有进行过什么深度理解,所以在一开始遇到了一些难题,例如购物车就是在整个研发过程当中所面临的最大问题,一开始实现时只是完成了界面,但对于添加或者删除的功能却存在着很多的问题,这个问题是一大难题,其中涉及到算法,界面交互等,但最终通过同学和查阅网上资料解决了。在解决这个最大的问题之后,心里感觉很开心,增加了自信,在以后遇到难题的时候有信心去克服。在完成毕业设计的过程中学到了,在书本上学到的东西是远远不够的。要想真正的从事这一行业,就必须多上手实操付诸实践。经过在实践中的磨练,才可以真正懂得理论,才会真正的掌握书本上的知识。经历毕业设计过后,发觉自己学到不只有专业知识,还有将实践与理论相结合的方法,在这整个的设计过程中,其中更多的是遇到困难永不后退的态度。

相关文章
|
安全 JavaScript Java
另一个生鲜App 抓包和mfsig签名分析(二) 针对flutter抓包
另一个生鲜App 抓包和mfsig签名分析(二) 针对flutter抓包
另一个生鲜App 抓包和mfsig签名分析(二) 针对flutter抓包
|
算法 安全
另一个生鲜App 抓包和mfsig签名分析(一)
另一个生鲜App 抓包和mfsig签名分析(一)
另一个生鲜App 抓包和mfsig签名分析(一)
|
Java Python Windows
某生鲜App 签名计算方法 脱个壳试试
某生鲜App 签名计算方法 脱个壳试试
某生鲜App 签名计算方法 脱个壳试试
|
1月前
|
API 数据安全/隐私保护 iOS开发
利用uni-app 开发的iOS app 发布到App Store全流程
利用uni-app 开发的iOS app 发布到App Store全流程
89 3
|
1月前
|
Android开发 开发者 UED
个人开发 App 成功上架手机应用市场的关键步骤
个人开发 App 成功上架手机应用市场的关键步骤
|
1月前
|
开发工具 数据安全/隐私保护 Android开发
【教程】APP 开发后如何上架?
【教程】APP 开发后如何上架?
|
1月前
|
API
uni-app 146朋友圈列表api开发
uni-app 146朋友圈列表api开发
18 0
|
1月前
|
Java Android开发 开发者
【Uniapp开发】APP的真机调试指南,从开发到上架全过程
【Uniapp开发】APP的真机调试指南,从开发到上架全过程
36 3
游戏直播APP平台开发多少钱成本:定制与成品源码差距这么大
开发一款游戏直播APP平台所需的费用是多少?对于计划投身这一领域的投资者来说,首要关心的问题之一就是。本文将探讨两种主要的开发模式——定制开发与成品源码二次开发的成本差异及其优劣势。
|
1月前
|
开发框架 移动开发 JavaScript
SpringCloud微服务实战——搭建企业级开发框架(四十六):【移动开发】整合uni-app搭建移动端快速开发框架-环境搭建
正如优秀的软件设计一样,uni-app把一些移动端常用的功能做成了独立的服务或者插件,我们在使用的时候只需要选择使用即可。但是在使用这些服务或者插件时一定要区分其提供的各种服务和插件的使用场景,例如其提供的【uni-starter快速开发项目模版】几乎集成了移动端所需的所有基础功能,使用非常方便,但是其许可协议只允许对接其uniCloud的JS开发服务端,不允许对接自己的php、java等其他后台系统。
145 2