电影购票APP实现(3)-Android客户端

FOE电影购票APP之Android客户端


  终于来到本次系列学习的尾声了,这次,我将会和大家一起做一个简单的Android APP,实现通过服务器访问数据库。

  还记得上一个博客给大家提前剧透的demo吗,不记得没关系~我再放一次。

AppDemo

  首先,我用的Android开发工具是Android Studio。用Eclispe的读者,你们看懂代码就好。

  我这里就不说怎么配置JDK,ADT之类的,包括layout文件的布局,甚至是跳转过去的listView, adapter之类的知识。我默认你们都会简单的Android开发咯。哈哈。我在本次博客的侧重点是,如何建立一个connection,并且访问服务器,获得我们想要的数据

  首先是第一个页面的登录功能,我们给登录按钮一个监听事件。

        Button btnLogin = (Button)findViewById(R.id.ButtonLogin);//获取登录按钮
        btnLogin.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String usernmae = etUsername.getText().toString();
                String password = etPassword.getText().toString();
                if (usernmae.isEmpty()) {
                    Toast.makeText(MainActivity.this, "用户名为空", Toast.LENGTH_SHORT).show();
                } else if (password.isEmpty()) {
                    Toast.makeText(MainActivity.this, "密码为空", Toast.LENGTH_SHORT).show();
                } else { 
                    Login(usernmae, password); //在用户名和密码不为空的前提下执行Login函数。
                }
            }
        });

  这里给大家再巩固一个知识,就是Android开发中的互联网访问是不可以在主线程中执行的,其实很多其他开发都一样,因为上网需要时间,下载资源等很容易会阻塞主线程,像Uinty的话,也是要放在协程中进行的。而在Android中,也提供了一些方法给我们简单的新开线程并且与界面进行交互。其中,我这次用的是异步任务类(AsyncTask)。

  我们来看看Login函数

    private void Login(String username, String password) {
        String loginUrl = LoginURL + "?Username=" + username + "&Password=" + password;
        new MyAsyncTask(MainActivity.this, username).execute(loginUrl);
    }

  很简单,哦,对了,大家记得在manifest中申请网络权限

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

  回过头来,我们的Login函数就是将我们的MainActivity的上下文和username作为MyAyncTask的构造函数参数来构造一个MyAyncTask实例,然后执行execyte(loginUrl)。

  现在我们看一下我们的MyAyncTask类

    public static class MyAsyncTask extends AsyncTask<String, Integer, String> {
        private Context context;
        private String uName;

        public  MyAsyncTask(Context context, String username) {
            this.context = context;
            this.uName = username;
        }

        @Override
        protected void onPreExecute() {

        }

        @Override
        protected  String doInBackground(String... params) {
            HttpURLConnection connection = null;
            StringBuilder response = new StringBuilder();
            try {
                URL url = new URL(params[0]);
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(8000);
                connection.setReadTimeout(8000);
                InputStream in = connection.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return response.toString();
        }

        @Override
        protected  void  onProgressUpdate(Integer... Values) {

        }

        @Override
        protected void onPostExecute(String s) {
            String text = s.substring(s.indexOf("resMsg=")+7);
            Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
            if ("登录成功}".equals(text)) {
                SharedPreferences userSharePreferences = context.getSharedPreferences("userInfo", Activity.MODE_PRIVATE);
                SharedPreferences.Editor editor = userSharePreferences.edit();
                editor.putString("username", uName);
                editor.commit();
                Intent intent = new Intent(context, FilmListActivity.class);
                context.startActivity(intent);
            }
        }
    }

  如果想透彻理解Android中这一个类的读者,可以自己去找相关的资料查阅,这里我说一下几个点,比较关键。

  首先是

public static class MyAsyncTask extends AsyncTask<String, Integer, String>

  我们看到这里有三个参数,分别是<输入, 进度, 输出>.第二个参数我们先不管,输入指的是我们执行该类时输入的参数类型,可以看到是和下列函数的传入参数类型一致,我们Login参数传入的就是一个String。

protected  String doInBackground(String... params)

  而上面函数的返回类型则和输出类型一致,同样和下面一个函数的传入参数类型一致。

protected void onPostExecute(String s)

  现在读者能够基本理解这个类了吧,就是在doInBackground中后台访问网络,然后得到结果后,在onPostExecute中执行,起码读者可以这样简单理解。

  至于访问的url,我们在上一篇中讲过,具体和数据库的交互,是在服务器中完成的。我们的客户端只需要明白我们给服务器的参数是什么,服务器将会返回什么给我们。

  大家可以看到,在登录成功后,我将会跳转到另一个Activity。

  这里,我想和大家说一下,我得到第二个Activity中图片的思路。

  首先我回访问这个url:

        //客户端
        String FilmListUrl = "http://192.168.110.1:8080/FoeServlet/FilmList";
        new MyAsyncTask(FilmListActivity.this, list, filmListAdapter).execute(FilmListUrl);

  我们来看一下,在服务端,会做什么。

        //服务器
        try {
            Statement statement = (Statement)connection.createStatement();
            String sql = "select * from " + DBUtil.TABLE_FILMLIST;
            ResultSet result = statement.executeQuery(sql);
            while (result.next()) {
                rs.append("name=");
                rs.append(result.getString(1));
                rs.append("introduce=");
                rs.append(result.getString(2));
                rs.append("actor=");
                rs.append(result.getString(3));
                rs.append("filmPic=");
                rs.append(result.getString(4));
                rs.append("\n");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }


        PrintWriter pw = response.getWriter();
        pw.println(rs.toString());
        pw.flush();

  服务器会访问film_list表,然后将里面的内容全部放在一个String里,返回给客户端。这里,我们是否还记得第一篇博客的一副图片,就是该表的内容。

数据库

  我们来看看服务器返回给客户端的字符串是怎样的吧。
返回数据

  哈哈,一眼看下去好像很乱,但其实不是的,当然,返回数据怎样组织由读者决定,反正我写的组织方法就是上图。大牛不要见笑。

  当客户端收到这一串字符串,我们只要这样处理。就可以提取有用的信息。

        @Override
        protected void onPostExecute(ArrayList<String> filmList) {
            for (int i = 0; i < filmList.size()-1; i++) {
                String filmData = filmList.get(i);
                String filmName = filmData.substring(filmData.indexOf("name=")+5, filmData.indexOf("introduce="));
                String filmIntroduce = filmData.substring(filmData.indexOf("introduce=")+10, filmData.indexOf("actor="));
                String filmActor = filmData.substring(filmData.indexOf("actor=")+6, filmData.indexOf("filmPic="));
                String filmPicURL = "http://192.168.110.1:8080/FoeServlet/FilmPic?PicID=" + filmData.substring(filmData.indexOf("filmPic=")+8);
                Bitmap filmPic = null;
                list.add(new Film(filmPic, filmName, filmIntroduce, filmActor));
                new MyPicLoad(list, i, filmListAdapter).execute(filmPicURL);
            }
            filmListAdapter.notifyDataSetChanged();
        }

  有兴趣的读者不要怕,晚点我会将源码放到github中,读者可以自己去看。我们看到,现在我们获得的图片只是一个ID,因为,我们没用必要在数据库中存储一张图片,我们只需要存储图片的url。这也是你在随便一个网站按F12,看到里面的图片其实都是src=**的原因。所以,我们需要我们拿到的图片ID,进行第二次的网络访问,获得图片。

  在第二次访问中,我们需要来自服务器的字节资源读取成图片。

        @Override
        protected  byte[] doInBackground(String... params) {
            HttpURLConnection connection = null;
            byte[] picByte = null;
            try {
                URL url = new URL(params[0]);
                connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("GET");
                connection.setReadTimeout(8000);

                if (connection.getResponseCode() == 200) {
                    InputStream fis = connection.getInputStream();
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    byte[] bytes = new byte[1024];
                    int length = -1;
                    while ((length = fis.read(bytes)) != -1) {
                        bos.write(bytes, 0, length);
                    }
                    picByte = bos.toByteArray();
                    bos.close();
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return picByte;
        }

  然后在获得图片后,再更新一次ListView就可以了。

        @Override
        protected void onPostExecute(byte[] filmPic) {
            if (filmPic != null) {
                Bitmap bitmap = BitmapFactory.decodeByteArray(filmPic, 0, filmPic.length);
                list.get(i).setFilmBitmap(bitmap);
                filmListAdapter.notifyDataSetChanged();
            }
        }

  本次的博客,就到这里结束了。本次项目将会上传到github

  github地址:https://github.com/gjbian/Foe_Ticket

  • 4
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
安卓Android电影院订票app设计可升级Studio 开发环境: Myclipse/Eclipse/Idea都可以(服务器端) + Eclipse(手机客户端) + mysql数据库 系统客户端和服务器端架构技术: 界面层,业务逻辑层,数据层3层分离技术,MVC设计思想! 服务器和客户端数据通信格式: XML格式(用于传输查询的记录集)和json格式(用于传输单个的对象信息) 影院系统在电影院有着重要的地位,它不仅保存着电影院的基本信息,而且会储存大量的用户个人信息。影院系统是电影院重要的组成部分,在有效管理电影信息的同时,对电影院的业务和模式以及统筹计划起着至关重要的作用。 本系统根据电影院的实际要求,结合考察电影院管理的实际流程,需要实现以下的功能。 客户端: 1.注册功能:新用户可以在手机端注册。 2登录功能:输入账号和密码,进行登录操作。 3.查询影片信息:选择相应的影片,查询影片的相关内容。 4.订票:选择相应的影片,订取该影片的影票。 5.关于:查看本软件的相关信息。 6.退出:退出当前登录。 服务器端: 1.影院信息:添加各电影院的基本信息,让用户可以看到该影院的影片资讯,并可以对其进行删除修改等操作。 2.影片信息:对上映的电影进行详细介绍,对播放地区、时间、是否推荐、上映影院进行增添、删除、修改等操作。 3.用户信息:对用户的个人信息进行浏览,并且可以对其进行管理。 实体ER属性: 用户: 用户名,登录密码,姓名,性别,出生日期,用户照片,联系电话,邮箱,家庭地址,注册时间 电影类型: 类型id,类型名称 电影: 电影id,影片类型,影片名称,影片图片,导演,主演,时长,地区,放映时间,票价,剧情简介,是否推荐,点击率 地区: 地区id,地区名称 订单: 订单编号,下单电影,电影价格,购买数量,订单总价,下单用户,下单时间,收货人,收货人电话,收货人地址,订单状态,订单备注 订单状态: 订单状态id,订单状态名称 -------- 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! <项目介绍> 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 --------

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值