Android手机商城

第一章需求分析
近几年来,随着互联网时代的发展,电子商务迅猛发展让人们的购物更方便,更随时随地。而商城购物App是专门为商业零售及服务企业开发的手机客户端,帮助商家快速形成自有的用户群体,通过免费的信息推送开展促销活动,有效提升销售业绩。简而言之,手机App购物商城就是通过网络推广把线上的消费者带到现实的商店中去在线支付,购买线下的商品和服务,再到线下去提货和享受服务。

一、项目定位
  ”机太美”手机商城APP是以实现用户足不出户就能够选购自己喜欢的手机为目的,以尽全力满足全体客户需求为宗旨的工具型应用APP软件。

二、APP竞品分析
表1 APP竞品分析

在这里插入图片描述
三、用户界面设计
  “机太美”手机商城APP的视觉设计尽量提供用户特点鲜明的功能和界面,达到用户体验的最佳化,给予用户良好的视觉体验。

第二章 概要设计
在这里插入图片描述
图1是整个手机商城APP的项目框架,分为客户端和服务端。客户端有三个部分:视图,模块,其中界面视图(view),也就是Activity和一些View模块,包括登陆,注册,产品,订单,购物车等界面,同时该部分还包含用户事件的捕捉和少量的逻辑处理,比如用户单击某个图标,界面的切换方式等操作;模块部分对于于上图的网络模块和数据模块,各个模块能提供不同的功能,视图调用数据模块中的数据进行显示。在客户端对于登陆注册采用了SharedPreference存储和SQLite存储。对于用户注销时,采用了Android的Service技术和广播技术来不时提醒用户尚多久未登陆以期实现产品的更大销售可能。
从MVC设计模式的角度去分析,服务端采用了SSM框架技术,Controler层,对客户端请求的数据转发处理,包括用户,订单,购物车,产品等。Service层,业务逻辑处理,包括用户的登陆注册,订单的状态改变,购物车的增删改查,产品的显示等处理操作。Mapper采用了Mybatis逆向工程技术对数据库进行一系列访问更新等操作。远端数据库采用了mysql数据库。

在这里插入图片描述

数据设计
在这里插入图片描述

3.2 界面设计
3.2.1 欢迎界面
WelcomeActivity,实现在2秒后进入应用程序。
在这里插入图片描述
3.2.2 注册界面
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
登陆界面:前台向后台发送用户名密码,后台检验并返回数据判断是否登陆成功。在成功登陆后运用了Android的SharePreferences存储技术在本机上保存了相应的用户登陆数据。
亮点:在这两个页面中,我们对注册和登录按钮添加了监听机制,即按钮初始颜色未灰色,不可点击,为不可用状态。只有当用户将所有的输入栏都填写完整后,按钮才变为橘色,可以出发点击事件。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

上图为订单界面,分为全部订单,待支付订单,待发货订单,待确认订单,和待评价订单。
当订单的状态改变时,数据库和客户端订单的状态同时更新。

在这里插入图片描述

3.3 关键技术
3.3.1网络连接访问
我们利用HttpURLConnection来进行网络通信,并封装了GET和POST两种方式用于与后台链接并传输数据。

private static final String MY_HOST_URL="http://192.168.1.107:8080/MarketServer";
    public static final String IMAGE_PATH="http://192.168.1.107:8080/MarketServer/upload/";
//    private static String sessionId;


    //GET请求需将参数进行封装
    public static  String get(String api,String param) throws IOException {
        String path=MY_HOST_URL+api+param;
        URL url = new URL(path);
        HttpURLConnection connection=(HttpURLConnection)url.openConnection();
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(3000);
        int code = connection.getResponseCode();
        String res=null;
        Log.i("code",code+"");
        if(code==200){
            InputStream inputStream = connection.getInputStream();
            InputStreamReader in=new InputStreamReader(inputStream);
            BufferedReader bufferedReader=new BufferedReader(in);
            res = bufferedReader.readLine();
            bufferedReader.close();
        }
        return res;
    }

    //post请求直接传实体类
    public static  String post(String api, Object obj) throws IOException {
        Log.i("httputil","httputil");
        String path=MY_HOST_URL+api;
        URL url = new URL(path);
        HttpURLConnection connection=(HttpURLConnection)url.openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type","application/json");
        connection.setConnectTimeout(3000);
        Gson gson = new Gson();
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(gson.toJson(obj).getBytes());
        int code = connection.getResponseCode();
        String res=null;
        Log.i("code",code+"");

        if(code==200){
            InputStream inputStream = connection.getInputStream();
            InputStreamReader in=new InputStreamReader(inputStream);
            BufferedReader bufferedReader=new BufferedReader(in);
            res = bufferedReader.readLine();
            bufferedReader.close();
        }
        return res;
    }

SharePreferences

public class UserSharePreference {
    public static boolean SaveUserInfo(Context context, User user)
    {
        SharedPreferences sharedPreferences=context.getSharedPreferences("user_mes",Context.MODE_PRIVATE);
        SharedPreferences.Editor editor=sharedPreferences.edit();
        editor.putInt("user_id",user.getUserId());
        editor.putString("user_name",user.getUserName());
        editor.commit();
        return  true;
    }

    public static User getUser_mes(Context context)
    {
        SharedPreferences sharedPreferences=context.getSharedPreferences("user_mes",Context.MODE_PRIVATE);
        String username=sharedPreferences.getString("user_name",null);
        int userid=sharedPreferences.getInt("user_id",1);
        if(username==null) return null;
        User user = new User(username,userid);
        return  user;
    }

    public  static void ClearData(Context context)
    {
        SharedPreferences sharedPreferences=context.getSharedPreferences("user_mes",Context.MODE_PRIVATE);
        sharedPreferences.edit().clear().commit();

3.3.3 service 和Notification
当用户注销后,我们通过开启Service在后台运行使得该APP退出后仍然会在一定的时间内通知用户尝试登陆,提高该APP的关注度,以期得到更好地发展。

3.3.3 service 和Notification
当用户注销后,我们通过开启Service在后台运行使得该APP退出后仍然会在一定的时间内通知用户尝试登陆,提高该APP的关注度,以期得到更好地发展。

public class NotifyService extends Service {
private NotificationManager mManager;
public static final String ANDROID_CHANNEL_ID = “com.ncusoft.notificationchannel.IOS”;
public static final String ANDROID_CHANNEL_NAME = “IOS CHANNEL”;

@Override
public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
}

private int id=0;
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onCreate() {
    createChannels();
    new Thread(){
        @Override
        public void run() {
            while (true){
                id++;
                Notification.Builder builder = new Notification.Builder(NotifyService.this, ANDROID_CHANNEL_ID)
                        .setContentTitle("机太美")
                        .setContentText("你已经"+id+"分钟没有光顾我们了")
                        .setSmallIcon(R.drawable.about)
                        .setAutoCancel(true);
                getManager().notify(id,builder.build());
                try {
                    Thread.sleep(60000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }.start();
}
@RequiresApi(api = Build.VERSION_CODES.O)
public void createChannels() {
    // create ios channel
    NotificationChannel iosChannel = new NotificationChannel(ANDROID_CHANNEL_ID,
            ANDROID_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
    iosChannel.enableLights(true);
    iosChannel.enableVibration(true);
    iosChannel.setLightColor(Color.BLUE);
    iosChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
    getManager().createNotificationChannel(iosChannel);

}

public NotificationManager getManager() {
    if (mManager == null) {
        mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    }
    return mManager;
}

}


3.3.4 BroadcastReceiver
我们注册了两个广播。其中,MyReceiver用来监听网络请求的返回结果。当网络请求成功时,则利用Toast来提示用户请求成功。而FinishReceiver则用来监听用户退出程序的操作,当用户退出程序时则启动上述的service 。

package com.ncuedu.marketclient.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String msg = intent.getStringExtra("msg");
        Toast.makeText(context,msg,Toast.LENGTH_SHORT).show();
    }
}
package com.ncuedu.marketclient.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.ncuedu.marketclient.service.NotifyService;

public class FinishReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //开启一个发送notification的service
        Intent intentService = new Intent(context, NotifyService.class);
        context.startService(intentService);
    }
}

CityPickerView框架的使用
在填写收货人信息的界面中,我们使用了Github上的开源框架CityPickerView。该框架可以实现选择地址时的三级联动。

case R.id.edt_area:{
    //隐藏键盘
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
    //添加默认的配置,不需要自己定义
    CityConfig cityConfig = new CityConfig.Builder().build();
    CityPickerView.getInstance().setConfig(cityConfig);
    //监听选择点击事件及返回结果
    CityPickerView.getInstance().setOnCityItemClickListener(new OnCityItemClickListener() {
        @Override
        public void onSelected(ProvinceBean province, CityBean city, DistrictBean district) {
            String res="";
            //省份
            if (province != null) {
                res+=province.toString();
            }
            //城市
            if (city != null) {
                res+=city.toString();
            }
            //地区
            if (district != null) {
                res+=district.toString();
            }
            editArea.setText(res);
        }
        @Override
        public void onCancel() {
            ToastUtils.showLongToast(SetOrderActivity.this, "已取消");
        }
    });
    CityPickerView.getInstance().showCityPicker( );
    break;
}

轮播图banner组件的使用
我们使用了banner组件来实现商品信息界面的轮播图功能。

public class ProductImgFragment extends Fragment implements OnBannerListener {

    private Banner banner;
    private ArrayList<String> list_path;
    private View view;
    private Product product;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_product_img, container, false);
        ShowProductActivity activity = (ShowProductActivity)getActivity();
        int productId = activity.getProductId();
        product=activity.getProduct();
        Log.i("product2222111",product.toString());
        initView();
        return view;
    }

    private void initData(){
        if(product.getProductImg1()!=null&&product.getProductImg1().length()>0){
            list_path.add(HttpUtil.IMAGE_PATH+product.getProductImg1());
        }
        if(product.getProductImg2()!=null&&product.getProductImg2().length()>0){
            list_path.add(HttpUtil.IMAGE_PATH+product.getProductImg2());
        }
        if(product.getProductImg3()!=null&&product.getProductImg3().length()>0){
            list_path.add(HttpUtil.IMAGE_PATH+product.getProductImg3());
        }
    }
    private void initView() {
        banner = view.findViewById(R.id.banner);
        list_path = new ArrayList<>();
        initData();
        banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR);
        banner.setImageLoader(new ProductImgFragment.MyLoader());
        banner.setBannerAnimation(Transformer.Default);
        banner.setDelayTime(3000);
        banner.isAutoPlay(true);
        banner.setIndicatorGravity(BannerConfig.CENTER);
        banner.setImages(list_path)
                .setOnBannerListener(this)
                .start();
    }

    @Override
    public void OnBannerClick(int position) {
        Toast.makeText(getContext(), "你点了第" + (position + 1) + "张轮播图", Toast.LENGTH_SHORT).show();
    }

    //自定义的图片加载器
    private class MyLoader extends ImageLoader {
        @Override
        public void displayImage(Context context, Object path, ImageView imageView) {
            Glide.with(context.getApplicationContext())
                    .load((String) path)
                    .into(imageView);
        }
    }
}

该手机商城APP后台采用了SSM整体架构
Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。
Spring的核心思想是IoC(控制反转),即不再需要程序员去显式地new一个对象,而是让Spring框架帮你来完成这一切。
SpringMVC在项目中拦截用户请求,它的核心Servlet即DispatcherServlet承担中介或是前台这样的职责,将用户请求通过HandlerMapping去匹配Controller,Controller就是具体对应请求所执行的操作。SpringMVC相当于SSH框架中struts。
mybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到各实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。

下载地址

https://download.csdn.net/download/lzm123456lq/11249381

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值