本文主要是介绍Android+leancloud实现火车实时管理系统模型(课设题目,写出来当笔记),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
火车实时管理系统模型
我先把代码和AKP文件链接贴出来
apk文件
代码,解压后用Android studio打开
设计一套火车管理系统,并能合理的调度火车的运行系统,并能提供购票系统,用户邮箱能获得购票信息
详细功能描述:
该火车管理系统包括以下模块:1)火车站信息 2)轨道信息,轨道由各种站点组成,两站点之间只有一条轨道,3)火车信息,或者调度信息如出站信息和进站信息等 4)客户预定火车票,包括火车,时间,出发站点,到达站点,车厢,座位和乘客信息
关键词
火车购票
目录
第一部分 设计任务 3
(一) 任务一 3
(二) 任务二 3
(三) 任务三 3
第二部分 功能模块 5
(一) 功能1——登录注册页面 5
(二) 功能2——侧滑菜单栏 10
(三) 功能3——显示列车信息 13
(四) 功能4——在线购票之路线、日期选择 15
(五) 功能5——在线购票之车次选择 19
(六) 功能6——在线购票之座位选择,购票确认 22
(七) 功能7——本地客户端查看购票记录 30
(八) 功能8——个人信息修改 33
(九) 功能9——小组成员及分工查看 36
第三部分 数据库 38
(一) leancloud数据库介绍: 38
(二) 构建用户信息表: 42
(三) 构建购票信息表: 42
第四部分 总结 43
课程设计总结 43
第一部分 设计任务
(一)任务一
用户能注册,登录进行购票操作

(二)任务二
设计3条火车路线,并提供购票流程

(三)任务三
用户购票,并能在客户端查询到购票记录,邮箱能收到通知邮件

第二部分 功能模块
(一)功能1——登录注册页面


用户首先点击注册,可以注册新用户,如图。用户名和密码均不能为空,邮箱需正确填写格式才能注册成功,注册成功后,用户表会生成一条用户数据:
本部分注册界面代码如下:
package mountain_hua.train;
import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.avos.avoscloud.AVException; import com.avos.avoscloud.AVObject; import com.avos.avoscloud.AVQuery; import com.avos.avoscloud.CountCallback; import com.avos.avoscloud.SaveCallback; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created by dhs on 2018/5/15. */
public class zhuce extends AppCompatActivity { private String name,pwd,email; private static final String EP="^[a-z0-9]+([._\\\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$";//邮箱格式 private static final String EPP="^[a-zA-Z0-9#_~!$&'()*+,;=:.\"(),:;<>@\\[\\]\\\\]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*$"; private Pattern pa=Pattern.compile(EPP); protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.zhuce); //注册按钮 Button b2=(Button)findViewById(R.id.button5); b2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { EditText ed4=(EditText)findViewById(R.id.editText4); name=ed4.getText().toString(); pwd=((EditText)findViewById(R.id.editText5)).getText().toString(); email=((EditText)findViewById(R.id.editText)).getText().toString(); zhuce();
} }); } //保存信息 void baocun(){ if(youxiang(email)) { AVObject inf = new AVObject("user_info"); inf.put("name", name); inf.put("pwd", pwd); inf.put("email", email); inf.saveInBackground(new SaveCallback() { @Override public void done(AVException e) { if (e == null) { Toast.makeText(zhuce.this, "注册成功,即将返回登录页面", Toast.LENGTH_SHORT).show(); finish(); } else { Toast.makeText(zhuce.this, "注册失败,请检查网络", Toast.LENGTH_SHORT).show(); } } }); } else { Toast.makeText(zhuce.this, "邮箱格式不正确", Toast.LENGTH_SHORT).show(); } }
void zhuce() { if(name.length()==0||pwd.length()==0) { Toast.makeText(zhuce.this, "用户名和密码不能为空", Toast.LENGTH_SHORT).show(); } else { AVQuery<AVObject> query = new AVQuery<>("user_info"); query.whereEqualTo("name", name); query.countInBackground(new CountCallback() { @Override public void done(int i, AVException e) { if (e == null) { // 查询成功,输出计数 if (i == 0) { baocun(); } else { Toast.makeText(zhuce.this, "该用户名已被注册,换个名字试试", Toast.LENGTH_SHORT).show();
} } else { // 查询失败 Toast.makeText(zhuce.this, "连接失败,请检查网络设置", Toast.LENGTH_SHORT).show();
}
} }); } } //邮箱格式 private boolean youxiang(String s){ Matcher matcher=pa.matcher(s); return matcher.matches(); }
} |
登录界面代码如下:
package mountain_hua.train;
import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.avos.avoscloud.AVException; import com.avos.avoscloud.AVObject; import com.avos.avoscloud.AVQuery; import com.avos.avoscloud.GetCallback;
/** * Created by dhs on 2018/5/15. */
public class denglu extends AppCompatActivity { private String name,pwd; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.denglu); //登录按钮 Button b1=(Button)findViewById(R.id.button4); b1.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
name=((EditText)findViewById(R.id.editText4)).getText().toString(); pwd=((EditText)findViewById(R.id.editText5)).getText().toString();
if(name.length()==0) { Toast.makeText(denglu.this, "请输入用户名!", Toast.LENGTH_SHORT).show(); } else if(pwd.length()==0){ Toast.makeText(denglu.this, "请输入密码!", Toast.LENGTH_SHORT).show(); } else {
AVQuery<AVObject> query = new AVQuery<>("user_info"); query.whereEqualTo("name", name); query.getFirstInBackground(new GetCallback<AVObject>() { @Override public void done(AVObject avObject, AVException e) { // object 就是符合条件的第一个 AVObject if (avObject.getString("pwd").equals(pwd)) { Intent i1 = new Intent(); i1.putExtra("name", name); i1.setClass(denglu.this, MainActivity.class); startActivity(i1); } else { Toast.makeText(denglu.this, "用户名或密码不正确", Toast.LENGTH_SHORT).show();
} } }); }
} }); //注册按钮 Button b2=(Button)findViewById(R.id.button5); b2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent Int1=new Intent(); Int1.setClass(denglu.this,zhuce.class); startActivity(Int1); } }); } } |
(二)功能2——侧滑菜单栏

本部分实现了安卓的侧滑栏显示我们的菜单,包含了:列车信息,在线购票,购票记录,个人信息等。点击就可以进入相应的功能界面
本部分代码如下:
package mountain_hua.train;
import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.design.widget.NavigationView; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { private String name; @Override protected void onCreate(Bundle savedInstanceState) { name=getIntent().getStringExtra("name"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.setDrawerListener(toggle); toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); }
@Override public void onBackPressed() { DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } else { super.onBackPressed(); } }
@Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; }
@Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { Uri uri = Uri.parse("http://www.12306.cn/mormhweb/"); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); }
return super.onOptionsItemSelected(item); }
@SuppressWarnings("StatementWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.train_info) { Intent t1=new Intent(); t1.setClass(this,train_info.class); startActivity(t1); } else if (id == R.id.buyingticket) { Intent t1=new Intent(); t1.setClass(this,buyingticket.class); t1.putExtra("name",name); startActivity(t1); } else if (id == R.id.person) { Intent t1=new Intent(); t1.setClass(this,person.class); t1.putExtra("name",name); startActivity(t1); } else if (id == R.id.blue) { Intent t1=new Intent(); t1.setClass(this,test1.class); t1.putExtra("name",name); startActivity(t1); } else if (id == R.id.el) { Intent t1=new Intent(); t1.setClass(this,el.class); startActivity(t1); }
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; } } |
(三)功能3——显示列车信息
我设置了3个路线,如图,已广安——成都为例,点击相应的路线就会出现改路线的车次信息。


本部分的代码如下:
package mountain_hua.train;
import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.ImageButton;
/** * Created by dhs on 2018/3/22. */
public class train_info extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.train_info); ImageButton ib1=(ImageButton)findViewById(R.id.imageButton1); ib1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent t1=new Intent(); t1.setClass(train_info.this,train_info_1.class); startActivity(t1); } }); ImageButton ib2=(ImageButton)findViewById(R.id.imageButton2); ib2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent t1=new Intent(); t1.setClass(train_info.this,train_info_2.class); startActivity(t1); } }); ImageButton ib3=(ImageButton)findViewById(R.id.imageButton3); ib3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent t1=new Intent(); t1.setClass(train_info.this,train_info_3.class); startActivity(t1); } }); } } |
(四)功能4——在线购票之路线、日期选择
点击菜单栏的在线购票可以进入第一个购票页面,选择路线和日期。


本部分代码如下:
package mountain_hua.train;
import android.app.DatePickerDialog; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.DatePicker; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List;
/** * Created by dhs on 2018/3/22. */
public class buyingticket extends AppCompatActivity { private Calendar cal; private int year,month,day; private String begin,dest,name; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.buyingticket); name=getIntent().getStringExtra("name"); final Spinner spinner=(Spinner) findViewById(R.id.spinner); final Spinner spinner2=(Spinner) findViewById(R.id.spinner2); final List<String>categories=new ArrayList<String>(); categories.add("广安"); categories.add("成都"); categories.add("重庆"); ArrayAdapter<String>dataAdapter=new ArrayAdapter<String>(buyingticket.this,android.R.layout.simple_spinner_item,categories); dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(dataAdapter); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { //选择列表项的操作 begin=categories.get(position); //Toast.makeText(buyingticket.this, "点击了" +begin, Toast.LENGTH_SHORT).show(); }
@Override public void onNothingSelected(AdapterView<?> parent) { //未选中时候的操作 } }); spinner2.setAdapter(dataAdapter); spinner2.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { //选择列表项的操作 dest=categories.get(position); }
@Override public void onNothingSelected(AdapterView<?> parent) { //未选中时候的操作 } }); //日期选择(日期限制未设置): getDate(); final TextView tx4=(TextView)findViewById(R.id.textView4); tx4.setText(year+"-"+(++month)+"-"+day); Button b1=(Button)findViewById(R.id.button3); b1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { DatePickerDialog.OnDateSetListener listener=new DatePickerDialog.OnDateSetListener() {
@Override public void onDateSet(DatePicker arg0, int year, int month, int day) { tx4.setText(year+"-"+(++month)+"-"+day); //将选择的日期显示到TextView中,因为之前获取month直接使用,所以不需要+1,这个地方需要显示,所以+1 } }; DatePickerDialog dialog=new DatePickerDialog(buyingticket.this, 0,listener,year,month,day);//后边三个参数为显示dialog时默认的日期,月份从0开始,0-11对应1-12个月 dialog.show(); } }); //取消按钮 Button b=(Button)findViewById(R.id.button); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); //查询按钮 Button b2=(Button)findViewById(R.id.button2); b2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //查询操作 if(begin==dest) { Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Toast.makeText(buyingticket.this, "起始站和终点站不应该相同"+sdf.format(date), Toast.LENGTH_SHORT).show(); }else { String way=begin+"——"+dest; Intent t1=new Intent(); t1.setClass(buyingticket.this,buyingticket_1.class); t1.putExtra("way",way); t1.putExtra("date",tx4.getText()); t1.putExtra("name",name); startActivity(t1); }
} }); } //获取日期 private void getDate() { cal=Calendar.getInstance(); year=cal.get(Calendar.YEAR); //获取年月日时分秒 Log.i("wxy","year"+year); month=cal.get(Calendar.MONTH); //获取到的月份是从0开始计数 day=cal.get(Calendar.DAY_OF_MONTH); } } |
(五)功能5——在线购票之车次选择

在选择好路线和日期后,进入车次选择,我设置的每个路线都有5趟车次,从早上八点到中午12点,一小时一趟。
本部分代码如下:
package mountain_hua.train;
import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap;
/** * Created by dhs on 2018/5/8. */
public class buyingticket_1 extends AppCompatActivity { private String way,name; private String date; private ListView lv2; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.buyingticket_1); way=getIntent().getStringExtra("way"); date=getIntent().getStringExtra("date"); name=getIntent().getStringExtra("name"); TextView t1=(TextView)findViewById(R.id.textView14); t1.setText(way); TextView t2=(TextView)findViewById(R.id.textView16); t2.setText(date); lv2 = (ListView) findViewById(R.id.lv2);/*定义一个动态数组*/ ArrayList<HashMap<String, Object>> listItem = new ArrayList <HashMap<String,Object>>();/*在数组中存放数据*/ for(int i=0;i<5;i++) { HashMap<String, Object> map = new HashMap<String, Object>(); int j=i+1; int t=i+8; switch (way){ case"广安——成都": map.put("ItemTitle", "车次:GA to CD."+j); break; case"成都——广安": map.put("ItemTitle", "车次:CD to GA."+j); break; case"广安——重庆": map.put("ItemTitle", "车次:GA to CQ."+j); break; case"重庆——成都": map.put("ItemTitle", "车次:CQ to CD."+j); break; case"重庆——广安": map.put("ItemTitle", "车次:CQ to GA."+j); break; case"成都——重庆": map.put("ItemTitle", "车次:CD to CQ."+j); break; }
map.put("ItemText2", "发车时间:"); map.put("ItemText",date+" "+t+":00:00"); listItem.add(map); } //new String 数据来源, new int 数据到哪去 SimpleAdapter mSimpleAdapter = new SimpleAdapter(this,listItem,R.layout.sample_adapter_item_1, new String[] {"ItemImage","ItemTitle","ItemText2", "ItemText"}, new int[] {R.id.ItemImage,R.id.ItemTitle,R.id.ItemText2,R.id.ItemText}); lv2.setAdapter(mSimpleAdapter);//为ListView绑定适配器 lv2.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { int j=arg2+1; int t=arg2+8; Intent it1=new Intent(); it1.setClass(buyingticket_1.this,buyingticket_1_1.class); switch (way){ case"广安——成都": it1.putExtra("way","GA to CD."+j); break; case"成都——广安": it1.putExtra("way","CD to GA."+j); break; case"广安——重庆": it1.putExtra("way","GA to CQ."+j); break; case"重庆——成都": it1.putExtra("way","CQ to CD."+j); break; case"重庆——广安": it1.putExtra("way","CQ to GA."+j); break; case"成都——重庆": it1.putExtra("way","CD to CQ."+j); break; } it1.putExtra("time",date+" "+t+":00:00"); it1.putExtra("lc",way); it1.putExtra("name",name); startActivity(it1); } });
} } |
(六)功能6——在线购票之座位选择,购票确认


用户选择车次后,进入此页面,选择车厢,排数,和座位号。并可以选择适合接收邮件提醒。如果开启邮件提醒。用户会在自己的邮箱内收到相应的购票信息,如下图:

本部分代码如下(本部分包含的代码量较多,提前预警):
package mountain_hua.train;
import android.content.DialogInterface; import android.os.Bundle; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast;
import com.avos.avoscloud.AVException; import com.avos.avoscloud.AVObject; import com.avos.avoscloud.AVQuery; import com.avos.avoscloud.AVUser; import com.avos.avoscloud.DeleteCallback; import com.avos.avoscloud.FindCallback; import com.avos.avoscloud.GetCallback; import com.avos.avoscloud.SaveCallback; import com.avos.avoscloud.SignUpCallback;
import java.util.ArrayList; import java.util.List;
/** * Created by dhs on 2018/5/13. */
public class buyingticket_1_1 extends AppCompatActivity { private String name,email,way; private String time; private String lc,cx,ps,zw; private String info; private boolean yx;//邮箱
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.buyingticket_1_1); way=getIntent().getStringExtra("way"); time=getIntent().getStringExtra("time"); lc=getIntent().getStringExtra("lc"); name=getIntent().getStringExtra("name"); //Toast.makeText(buyingticket_1_1.this, name+"cehi", Toast.LENGTH_SHORT).show(); get_email();//获得邮箱 TextView t1=(TextView)findViewById(R.id.textView20); t1.setText(way); TextView t2=(TextView)findViewById(R.id.textView21); t2.setText(time); //spinner final Spinner spinner3=(Spinner) findViewById(R.id.spinner3); final Spinner spinner4=(Spinner) findViewById(R.id.spinner4); final Spinner spinner5=(Spinner) findViewById(R.id.spinner5); final List<String> categories=new ArrayList<String>(); final List<String> categories2=new ArrayList<String>(); final List<String> categories3=new ArrayList<String>(); for(int i=1;i<=10;i++){ categories.add(i+"号车厢"); categories2.add(i+"排"); } categories3.add("A座"); categories3.add("B座"); categories3.add("C座"); categories3.add("D座"); categories3.add("E座"); ArrayAdapter<String> dataAdapter=new ArrayAdapter<String>(buyingticket_1_1.this,android.R.layout.simple_spinner_item,categories); dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner3.setAdapter(dataAdapter); spinner3.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { //选择列表项的操作 cx=categories.get(position); }
@Override public void onNothingSelected(AdapterView<?> parent) { //未选中时候的操作 } }); ArrayAdapter<String> dataAdapter2=new ArrayAdapter<String>(buyingticket_1_1.this,android.R.layout.simple_spinner_item,categories2); dataAdapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner4.setAdapter(dataAdapter2); spinner4.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { //选择列表项的操作 ps=categories2.get(position); }
@Override public void onNothingSelected(AdapterView<?> parent) { //未选中时候的操作 } }); ArrayAdapter<String> dataAdapter3=new ArrayAdapter<String>(buyingticket_1_1.this,android.R.layout.simple_spinner_item,categories3); dataAdapter3.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner5.setAdapter(dataAdapter3); spinner5.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { //选择列表项的操作 zw=categories3.get(position); }
@Override public void onNothingSelected(AdapterView<?> parent) { //未选中时候的操作 } }); //check box CheckBox cb=(CheckBox)findViewById(R.id.checkBox); cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked){ yx=true; }else{ yx=false; } } });
//确认按钮 Button b1=(Button)findViewById(R.id.button7); b1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new AlertDialog.Builder(buyingticket_1_1.this).setTitle("请确认信息")//设置对话框标题
.setMessage("您购买"+lc+"选择的车次是"+way+" " + "出发时间:"+time+" "+ "车厢:"+cx+" " + "排数:"+ps+" " + "座位号:"+zw)//设置显示的内容 .setPositiveButton("确定",new DialogInterface.OnClickListener() {//添加确定按钮 @Override public void onClick(DialogInterface dialog, int which) {//确定按钮的响应事件 // TODO Auto-generated method stub //保存数据 baocun();
//发邮件 if(yx) {
AVUser user = new AVUser();// 新建 AVUser 对象实例 info = name+",您购买" + lc + "选择的车次是" + way + " " + "出发时间:" + time + " " + "车厢:" + cx + " " + "排数:" + ps + " " + "座位号:" + zw; user.setUsername(info);// 设置用户名 user.setPassword("cat!@#123");// 设置密码 user.setEmail(email);// 设置邮箱 user.signUpInBackground(new SignUpCallback() { @Override public void done(AVException e) { if (e == null) { // 注册成功
Toast.makeText(buyingticket_1_1.this, "邮件发送成功", Toast.LENGTH_SHORT).show(); } else { // 失败的原因可能有多种,常见的是用户名已经存在。 Toast.makeText(buyingticket_1_1.this, "邮箱发送失败,请检查网络或邮箱是否正确", Toast.LENGTH_SHORT).show(); } } }); //删除User,方便重新发邮件 delete();
} else { Toast.makeText(buyingticket_1_1.this, "购票成功", Toast.LENGTH_SHORT).show(); }
}
}).setNegativeButton("返回",new DialogInterface.OnClickListener() {//添加返回按钮 @Override public void onClick(DialogInterface dialog, int which) {//响应事件 // TODO Auto-generated method stub }
}).show();//在按键响应事件中显示此对话框 } });
} //删除操作 void delete(){
final AVQuery<AVUser> query1 = new AVQuery<>("_User");
query1.whereEqualTo("email", email); query1.findInBackground(new FindCallback<AVUser>() { @Override public void done(List<AVUser> list, AVException e) { if(e==null) { query1.deleteAllInBackground(new DeleteCallback() { @Override public void done(AVException e) {
} }); } else{
} } }); } //保存信息 void baocun(){ AVObject inf=new AVObject("info"); inf.put("name",name); inf.put("lc",lc); inf.put("way",way); inf.put("zw",zw); inf.put("cx",cx); inf.put("ps",ps); inf.put("time",time); inf.saveInBackground(new SaveCallback() { @Override public void done(AVException e) { if(e==null){ Toast.makeText(buyingticket_1_1.this, "购票成功", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(buyingticket_1_1.this, "购票失败,请检查网络", Toast.LENGTH_SHORT).show(); } } }); } //获得邮箱 void get_email(){ AVQuery<AVObject> query = new AVQuery<>("user_info"); query.whereEqualTo("name",name); query.getFirstInBackground(new GetCallback<AVObject>() { @Override public void done(AVObject avObject, AVException e) { // object 就是符合条件的第一个 AVObject email=avObject.getString("email");
} }); }
} |
(七)功能7——本地客户端查看购票记录

当用户购票完成后,可以返回菜单栏查看购票记录,系统会从云端自动加载购票记录到客户端。用户可以滑动查看
本部分代码如下:
package mountain_hua.train;
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast;
import com.avos.avoscloud.AVException; import com.avos.avoscloud.AVObject; import com.avos.avoscloud.AVQuery; import com.avos.avoscloud.FindCallback;
import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List;
/** * Created by dhs on 2018/3/22. */
public class person extends AppCompatActivity { private ListView lv; private String way; private String time; private String lc,cx,ps,zw; private String name,creatat; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.person); name=getIntent().getStringExtra("name"); // ArrayList<HashMap<String, Object>> listItem = new ArrayList <HashMap<String,Object>>();/*在数组中存放数据*/
AVQuery<AVObject> query = new AVQuery<>("info"); query.whereEqualTo("name",name); query.orderByDescending("createdAt"); query.findInBackground(new FindCallback<AVObject>() { final ArrayList<HashMap<String, Object>> listItem = new ArrayList <HashMap<String,Object>>();/*在数组中存放数据*/ @Override
public void done(List<AVObject> list, AVException e) { for(AVObject account :list){ lc=account.getString("lc"); way=account.getString("way"); time=account.getString("time"); cx=account.getString("cx"); ps=account.getString("ps"); zw=account.getString("zw"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); creatat=sdf.format(account.getDate("createdAt")); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("ItemImage", R.drawable.b2);//加入图片 map.put("ItemTitle", lc); map.put("tx1","购票时间:"); map.put("tx2",creatat); map.put("tx3","发车时间:"); map.put("ItemText2", "车次:"+way); map.put("ItemText",time); map.put("ItemText4", "车厢:"+cx); map.put("ItemText5", "排数:"+ps); map.put("ItemText6", "座位:"+zw); listItem.add(map); lv = (ListView) findViewById(R.id.lv); //new String 数据来源, new int 数据到哪去 SimpleAdapter mSimpleAdapter = new SimpleAdapter(person.this,listItem,R.layout.sample_adapter_item, new String[] {"ItemImage","ItemTitle","tx1","tx2","tx3","ItemText2", "ItemText","ItemText4","ItemText5","ItemText6"}, new int[] {R.id.ItemImage,R.id.ItemTitle,R.id.tx1,R.id.tx2,R.id.tx3,R.id.ItemText2,R.id.ItemText,R.id.ItemText4,R.id.ItemText5,R.id.ItemText6}); lv.setAdapter(mSimpleAdapter);//为ListView绑定适配器 lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { } }); }
if (e == null) {
Toast.makeText(person.this, "查询成功", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(person.this, "查询失败,请检查网络", Toast.LENGTH_SHORT).show(); } }
});
}
} |
(八)功能8——个人信息修改

从菜单栏进入个人信息修改界面,系统会先从云端加载个人信息(用户名我们设置的唯一且不可修改),可以修改密码和邮箱(邮箱会通过正则表达式确认是否正确,不正确会提示格式不正确)。
本部分代码如下:
package mountain_hua.train;
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast;
import com.avos.avoscloud.AVException; import com.avos.avoscloud.AVObject; import com.avos.avoscloud.AVQuery; import com.avos.avoscloud.GetCallback;
import java.util.regex.Matcher; import java.util.regex.Pattern;
/** * Created by dhs on 2018/3/21. */
public class test1 extends AppCompatActivity { private String name,email,pwd; private static final String EP="^[a-z0-9]+([._\\\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$";//邮箱格式 private static final String EPP="[^a-zA-Z0-9#_~!$&'()*+,=;=:.\"(),:;<>@\\[\\]\\\\]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*$"; private Pattern pa=Pattern.compile(EP); protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test1); name=getIntent().getStringExtra("name");
final EditText ed1=(EditText)findViewById(R.id.editText4); ed1.setKeyListener(null); final EditText ed2=(EditText)findViewById(R.id.editText5); final EditText ed3=(EditText)findViewById(R.id.editText); // AVQuery<AVObject> query = new AVQuery<>("user_info"); query.whereEqualTo("name",name); query.getFirstInBackground(new GetCallback<AVObject>() { @Override public void done(AVObject avObject, AVException e) { // object 就是符合条件的第一个 AVObject email=avObject.getString("email"); pwd=avObject.getString("pwd"); if(e==null){ ed1.setText(name); ed2.setText(pwd); ed3.setText(email); } } });
Button b1=(Button)findViewById(R.id.button5); b1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AVQuery<AVObject> query = new AVQuery<>("user_info"); query.whereEqualTo("name",name); query.getFirstInBackground(new GetCallback<AVObject>() { @Override public void done(final AVObject avObject, AVException e) { // object 就是符合条件的第一个 AVObject String s=ed3.getText().toString(); String m=ed2.getText().toString(); if(youxiang(s)&&m.length()!=0) { avObject.put("pwd", ed2.getText()); avObject.put("email", ed3.getText()); avObject.saveInBackground();
if (e == null) { Toast.makeText(test1.this, "保存成功" , Toast.LENGTH_SHORT).show(); } else { Toast.makeText(test1.this, "保存失败,请检查网络", Toast.LENGTH_SHORT).show(); } } else if(m.length()==0) { Toast.makeText(test1.this,"密码不能为空", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(test1.this,"邮箱格式不正确", Toast.LENGTH_SHORT).show(); } } }); } }); } //邮箱格式 private boolean youxiang(String s){ Matcher matcher=pa.matcher(s); return matcher.matches(); }
} |
(九)功能9——小组成员及分工查看
在这里我截取了各组员的QQ头像作为imageButton。点击各组员头像可以查看分工情况(其实都是我一人完成的,但组员也要有成绩呀)


本部分代码如下:
package mountain_hua.train;
import android.os.Bundle; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.AdapterView; import android.widget.GridView; import android.widget.SimpleAdapter;
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;
/** * Created by dhs on 2018/5/13. */
public class el extends AppCompatActivity { private GridView gridView; private List<Map<String, Object>> dataList; private SimpleAdapter adapter;
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.el);
gridView = (GridView) findViewById(R.id.gridview); //初始化数据 initData();
String[] from={"img","text"};
int[] to={R.id.img,R.id.text};
adapter=new SimpleAdapter(this, dataList, R.layout.gridview_item, from, to);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { AlertDialog.Builder builder= new AlertDialog.Builder(el.this); switch (arg2){ case 0: builder.setTitle("邓华山").setMessage("组长,代码撰写,文档撰写").create().show(); break; case 1: builder.setTitle("汪瑞").setMessage("组员,数据库构建,文档撰写").create().show(); break; case 2: builder.setTitle("旦增曲珍").setMessage("组员,信息采集,文档撰写").create().show(); break; case 3: builder.setTitle("赵振廷").setMessage("组员,测试bug,文档撰写").create().show(); break; case 4: builder.setTitle("伊娃").setMessage("组员,测试bug,文档撰写").create().show(); break; }
} }); }
void initData() { //图标 int icno[] = { R.drawable.dhs,R.drawable.wr,R.drawable.qz,R.drawable.zzt,R.drawable.yw, }; //图标下的文字 String name[]={"邓华山","汪瑞","旦曾曲珍","赵振廷","伊娃",}; dataList = new ArrayList<Map<String, Object>>(); for (int i = 0; i <icno.length; i++) { Map<String, Object> map=new HashMap<String, Object>(); map.put("img", icno[i]); map.put("text",name[i]); dataList.add(map); }
} } |
第三部分 数据库
(一)leancloud数据库介绍:
下面这条 SQL 语句在绝大数的关系型数据库都可以执行,其结果是在 Todo 表里增加一条新数据:
+
INSERT INTO Todo (title, content) VALUES ('工程师周会', '每周工程师会议,周一下午 2 点')
+
使用传统的关系型数据库作为应用的数据源几乎无法避免以下步骤:
+
· 插入数据之前一定要先创建一个表结构,并且随着之后需求的变化,开发者需要不停地修改数据库的表结构,维护表数据。
· 每次插入数据的时候,客户端都需要连接数据库来执行数据的增删改查(CRUD)操作。
使用 LeanStorage,实现代码如下:
+
AVObject todo = new AVObject("Todo");
todo.put("title", "工程师周会");
todo.put("content", "每周工程师会议,周一下午2点");
todo.saveInBackground(new SaveCallback() {
@Override
public void done(AVException e) {
if (e == null) {
// 存储成功
} else {
// 失败的话,请检查网络环境以及 SDK 配置是否正确
}
}
});
+
使用 LeanStorage 的特点在于:
+
· 不需要单独维护表结构。例如,为上面的 Todo 表新增一个 location 字段,用来表示日程安排的地点,那么刚才的代码只需做如下变动:
AVObject todo = new AVObject("Todo");
todo.put("title", "工程师周会");
todo.put("content", "每周工程师会议,周一下午2点");
todo.put("location", "会议室");// 只要添加这一行代码,服务端就会自动添加这个字段
todo.saveInBackground(new SaveCallback() {
@Override
public void done(AVException e) {
if (e == null) {
// 存储成功
} else {
// 失败的话,请检查网络环境以及 SDK 配置是否正确
}
}
});
+
· 数据可以随用随加,这是一种无模式化(Schema Free)的存储方式。
· 所有对数据的操作请求都通过 HTTPS 访问标准的 REST API 来实现。
· 各个平台或者语言开发的 SDK 在底层都是调用统一的 REST API,并提供完整的接口对数据进行增删改查。
LeanStorage 在结构化数据存储方面,与 DB 的区别在于:
+
1. Schema Free/Not free 的差异;
2. 数据接口上,LeanStorage 是面向对象的(数据操作接口都是基于 Object 的),开放的(所有移动端都可以直接访问),DB 是面向结构的,封闭的(一般在 Server 内部访问);
3. 数据之间关联的方式,DB 是主键外键模型,LeanStorage 则有自己的关系模型(Pointer、Relation 等);
LeanStorage 支持两种存储类型:
+
· 对象
· 文件
(二)构建用户信息表:
我们构建用户信息:name,pwd,email,以及leancloud自动生成的createdAt,和updatedAt.
如图:
字段 | 类型 | 主键 | Notnull | 默认 | 说明 |
Name | String | 是 | 是 | | 用户名 |
Pwd | String | 否 | 是 | | 密码 |
Email | String | 否 | 是 | | 电子邮箱 |
下图是我们的用户:

(三)构建购票信息表:
我们设置了name,time,lc,way,zw,cx,ps,以及leancloud自动创建的createdAt和updatedAt。
如图:
字段 | 类型 | 主键 | Notnull | 默认 | 说明 |
Name | String | 是 | 是 | | 用户名 |
Time | String | 否 | 是 | | 出发时间 |
Lc | String | 否 | 是 | | 路程 |
Way | String | 否 | 是 | | 车次 |
zw | String | 否 | 是 | | 座位号 |
cx | String | 否 | 是 | | 车厢号 |
ps | String | 否 | 是 | | 车厢的排数 |
下面是我们的购票信息:

第四部分 总结
此次课程设计大概花了四五天的课余时间吧,总的来说没遇到什么大问题,还是很顺利的
这篇关于Android+leancloud实现火车实时管理系统模型(课设题目,写出来当笔记)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!