前言

【BMI指数计算器V4.0】与【BMI指数计算器V3.0】实现的效果是一样的,不同的是在【BMI指数计算器V3.0】的基础上加入了Service层(服务),BroadcastReceiver(广播接收者),使得项目的架构较V3.0多了一层。之所以使用Service(服务),是为了让数据库这样的与界面无关的业务逻辑放到Service(服务)中去处理,这也正是Service(服务)所擅长的。我们知道Android 有四大组件,分别是Activity(活动),Service(服务),BroadcastReceiver(广播接收者)ContentProvider(内容提供者)。而这四大组件各自所擅长的都不一样。

比如 :

(1)Activity擅长处理界面显示与界面交互工作;

 (2)Service擅长处理与界面无关,专门在后台进程中执行的操作;

 (3)BroadcastReceiver擅长接收系统广播以及Activity与Service之间的数据传递工作;

 (4)ContentProvider擅长让不同应用程序间共享数据。

更新列表

1.项目架构增加了Service层和BroadcastReceiver

2.数据模型Bmi类实现了一个标识接口 Serializable

3.其他的都与V3.0保持一致

项目架构图

技术预报

  1.Sevice(服务组件技术)
   2.BroadcastReceiver(广播接收者组件技术)
   3.数据对象或集合在不同组件间的传递(需要让数据模型类实现标识接口 Serializable) 
 

界面开发

        V4.0主要是在V3.0的基础上将项目的架构换成用Service去操作SQLite数据库,得到数据后发广播,让BroadcastReceiver去接收,在界面方面并没有改动,如果对界面开发不清楚的朋友请参考V3.0。

功能开发

 step1:数据模型层:com.kedi.bmi.model/Bmi.java

package com.kedi.bmi.model;import java.io.Serializable;/*** 指数数据实体类(数据模型) 实现一个标识接口Serializable(代表Bmi可以持久化,可放入Intent在各组件之间传递)* * @author 科弟* */
public class Bmi <span style="color:#ff0000;">implements Serializable</span> {/*** */private static final long serialVersionUID = 1L;// 唯一标识private int id;// 身高private double heigth;// 体重private double weigth;// 体重指数private double bmiNum;// 体重状态private String bmiState;// 体重状态图片名private String stateIconId;// 计算时间private long calaTime;/*** 构造方法*/public Bmi() {}/*** 构造方法* * @param id* @param heigth* @param weigth* @param bmiNum* @param bmiState* @param stateIconId* @param calaTime*/public Bmi(int id, double heigth, double weigth, double bmiNum,String bmiState, String stateIconId, long calaTime) {super();this.id = id;this.heigth = heigth;this.weigth = weigth;this.bmiNum = bmiNum;this.bmiState = bmiState;this.stateIconId = stateIconId;this.calaTime = calaTime;}public int getId() {return id;}public void setId(int id) {this.id = id;}public double getHeigth() {return heigth;}public void setHeigth(double heigth) {this.heigth = heigth;}public double getWeigth() {return weigth;}public void setWeigth(double weigth) {this.weigth = weigth;}public double getBmiNum() {return bmiNum;}public void setBmiNum(double bmiNum) {this.bmiNum = bmiNum;}public String getBmiState() {return bmiState;}public void setBmiState(String bmiState) {this.bmiState = bmiState;}public String getStateIconId() {return stateIconId;}public void setStateIconId(String stateIconId) {this.stateIconId = stateIconId;}public long getCalaTime() {return calaTime;}public void setCalaTime(long calaTime) {this.calaTime = calaTime;}@Overridepublic String toString() {return "Bmi [id=" + id + ", heigth=" + heigth + ", weigth=" + weigth+ ", bmiNum=" + bmiNum + ", bmiState=" + bmiState+ ", stateIconId=" + stateIconId + ", calaTime=" + calaTime+ "]";}}

  step2:Service(服务)层:com.kedi.bmi.service/DataService.java
<span style="font-size:14px;">package com.kedi.bmi.service;import java.io.Serializable;
import java.util.List;import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;import com.kedi.bmi.dao.BmiDao;
import com.kedi.bmi.model.Bmi;/*** 数据服务* * @author 科弟* 数据服务:(1)创建数据服务public class DataService extends Service ;(2)编写数据服务逻辑(对数据库的增,删,改,查);(3)在AndroidManifest.xml中注册数据服务DataService;(4)在MainActivity的onCreate()方法中通过startService()方法启动服务;在onDestroy()方法中通过stopService()方法停止服务;(5)在计算方法中给数据服务发送插入数据的方法;(6)在HistoryRecordActivity的onCreate()方法中给数据服务发送获取数据的命令;(7)获得数据后通过发广播将数据发到 HistoryRecordActivity中,广播接收者接收到广播,获取广播中的数据,然后完成数据的显示逻辑;(8)在对应的删除方法中给数据服务发送删除或清空的命令,让数据服务完成删除或清空功能。*/
public class DataService extends Service {// 数据服务的actionpublic static final String SERVICE_ACTION = "com.kedi.bmi.service.dataservice";// 接收数据的广播接收者actionpublic static final String RECEIVER_ACTION = "com.kedi.bmi.queryBmis";// 插入历史记录数据的命令标识valuepublic static final int INSERT = 0x1;// 删除某条历史记录的命令标识valuepublic static final int DELETE_ITEM = 0x2;// 清除所有历史记录的命令标识valuepublic static final int DELETE_ALL = 0x3;// 更新某条历史记录的命令标识valuepublic static final int UPDATE = 0x4;// 查询所有历史记录的命令标识valuepublic static final int QUERY = 0x5;// 命令命令标识Keypublic static final String COMMAND = "command";// 传递Bmi数据到数据服务的Keypublic static final String KEY_BMI = "bmi";// 传递Bmi集合数据到数据服务的Keypublic static final String KEY_BMIS = "bmis";// 操作数据库的业务逻辑类private BmiDao mBmiDao;@Overridepublic void onCreate() {super.onCreate();mBmiDao = new BmiDao(this);}@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {if (intent != null) {int command = intent.getIntExtra(COMMAND, QUERY);switch (command) {case INSERT:// 插入历史记录数据到数据库Bmi bmiInsert = (Bmi) intent.getSerializableExtra(KEY_BMI);if (bmiInsert != null) {mBmiDao.insertBmi(bmiInsert);}break;case DELETE_ITEM:// 从数据库中删除某条历史记录Bmi bmiDelete = (Bmi) intent.getSerializableExtra(KEY_BMI);if (bmiDelete != null) {mBmiDao.deleteBmi(bmiDelete);}break;case DELETE_ALL:// 清除数据库中所有历史记录mBmiDao.deleteBmis();break;case UPDATE:// 更新数据库中的某条历史记录Bmi bmiUpdate = (Bmi) intent.getSerializableExtra(KEY_BMI);if (bmiUpdate != null) {mBmiDao.updateBmi(bmiUpdate);}break;case QUERY:// 查询数据库中所有的历史记录// 创建获取数据的异步任务类并调用execute()方法执行异步任务new InsertDataAsynkTask().execute();break;default:break;}}return super.onStartCommand(intent, flags, startId);}@Overridepublic boolean onUnbind(Intent intent) {return super.onUnbind(intent);}@Overridepublic void onDestroy() {super.onDestroy();}/*** 从数据库查询数据的一步任务类(查询数据库是耗时操作,最好用一步方式)* * @author 科弟* */class InsertDataAsynkTask extends AsyncTask<Void, Void, List<Bmi>> {/*** 子线程方法,做好事操作*/@Overrideprotected List<Bmi> doInBackground(Void... arg0) {return mBmiDao.getBmis();}@Overrideprotected void onPostExecute(List<Bmi> result) {super.onPostExecute(result);// 将数据传给HisoryRecordActivity组件中// 这里我们用广播的方式传递数据Intent intent = new Intent(RECEIVER_ACTION);Bundle bundle = new Bundle();//将要传递的数据存到Bundle中,bundle.putSerializable(KEY_BMIS, (Serializable) result);//将Bundle存到intent中,以方便在发广播的时候把数据传递到Activity中//在Activity中通过Intent可获得Intent中存放的数据intent.putExtras(bundle);sendBroadcast(intent);}}
}</span><span style="font-size: 18px;">
</span>

step3:将数据服务注册到AndroidManifest.xml文件中


<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.kedi.bmi"android:versionCode="4"android:versionName="4.0" ><!-- 配置SDK的最小版本号为14,最大版本号为19 --><uses-sdkandroid:minSdkVersion="14"android:targetSdkVersion="19" /><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><!-- 注册主界面Activity --><activityandroid:name=".ui.MainActivity"android:screenOrientation="portrait" ></activity><!-- 注册欢迎界面Activity --><activityandroid:name=".ui.WelcomeActivity"android:screenOrientation="portrait" ><!-- 配置action,category,使得WelcomeActivity成为第一启动界面 --><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name=".ui.HistoryRecordActivity"android:screenOrientation="portrait" /><span style="color:#ff0000;"><!-- 注册数据服务DataService --><serviceandroid:name=".service.DataService"android:permission="permission.DataService" ><intent-filter><action android:name="com.kedi.bmi.service.dataservice" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></service></span></application></manifest></span>

step4:修改MainActivity相对应的代码部分(红色字体部分为修改)
package com.kedi.bmi.ui;import java.text.DecimalFormat;import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;
import android.widget.Toast;import com.kedi.bmi.R;
import com.kedi.bmi.listener.OnClickOkListener;
import com.kedi.bmi.model.Bmi;
import com.kedi.bmi.service.DataService;
import com.kedi.bmi.utils.DataUtil;
import com.kedi.bmi.utils.DialogUtil;/*** BMI指数计算器主界面管理类* * @author 科弟* */
@SuppressLint("ShowToast")
public class MainActivity extends Activity implements OnClickListener,OnCheckedChangeListener {private EditText mHeightInputEt;// 身高输入框private EditText mWeightInputEt;// 体重输入框private Button mCalaBtn;// 计算按钮private LinearLayout mResultLl;// 计算结果布局private TextView mWeightBmiTv;// 体重指数文本private TextView mWeightStateTv;// 体重状态文本private Button mClearBtn;// 清除按钮private double height;// 身高private double weight;// 体重private double bmi;// bmi指数值private String state;// 体重状态private String weightBmi;// 您的体重指数:private String weightState;// 您的体重状况:private ImageView mStateIv;// 体重状态图标// 可取体重状态值数组private String[] states = { "偏瘦", "正常", "偏胖", "肥胖", "重度肥胖", "极重度肥胖" };// 体重状态图片id数组private int[] state_imageIds = { R.drawable.r1, R.drawable.r2,R.drawable.r3, R.drawable.r4, R.drawable.r5, R.drawable.r6 };private int state_imageId;// 当前体重状态图片id// 标准相关布局或控件private RadioGroup mStandardRg;// 标准可选组布局private RadioButton mWhoStandardRb;// WHO标准单选按钮private RadioButton mAreaStandardRb;// 亚洲标准单选按钮private static final int WHO_STANDARD = 0x1;// WHO标准private static final int AREA_STANDARD = 0x2;// 亚洲标准private int mCurrentStandard = WHO_STANDARD;// 当前标准private SharedPreferences sp;// 保存小量数据的类,数据会保存到指定文件名的XML文件中private static final String FILE_NAME = "data.xml";// 文件名// 历史记录相关private ImageButton mHistoryIb;<span style="color:#ff0000;">// 数据服务相关Intentprivate Intent intent;</span>@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 去掉系统标题栏requestWindowFeature(Window.FEATURE_NO_TITLE);// 关联布局文件setContentView(R.layout.activity_main);// 初始化布局或控件initView();// 注册控件点击事件setViewListener();weightBmi = getResources().getString(R.string.weight_bmi);// 您的体重指数:weightState = getResources().getString(R.string.weight_state);// 您的体重状况:<span style="color:#ff0000;">// 开启数据服务的方法startDataService();</span>}/*** 初始化布局或控件的方法*/private void initView() {mHeightInputEt = (EditText) this.findViewById(R.id.et_height);// 身高输入框mWeightInputEt = (EditText) this.findViewById(R.id.et_weight);// 体重输入框mCalaBtn = (Button) this.findViewById(R.id.btn_cala);// 计算按钮mResultLl = (LinearLayout) this.findViewById(R.id.ll_result);// 计算结果布局mWeightBmiTv = (TextView) this.findViewById(R.id.tv_bmi);// 体重指数文本mWeightStateTv = (TextView) this.findViewById(R.id.tv_state);// 体重状态文本mStateIv = (ImageView) this.findViewById(R.id.iv_state);mClearBtn = (Button) this.findViewById(R.id.btn_clear);// 清除按钮// 默认显示计算按钮(VISIBLE),隐藏结果布局(GONE)mCalaBtn.setVisibility(View.VISIBLE);mResultLl.setVisibility(View.GONE);mStandardRg = (RadioGroup) this.findViewById(R.id.rg_standard);// 标准可选组布局mWhoStandardRb = (RadioButton) this.findViewById(R.id.rb_who);// WHO标准单选按钮mAreaStandardRb = (RadioButton) this.findViewById(R.id.rb_area);// 亚洲标准单选按钮// 历史记录相关mHistoryIb = (ImageButton) this.findViewById(R.id.ib_history);}/*** 注册控件点击事件的方法*/private void setViewListener() {// 注册点击事件mCalaBtn.setOnClickListener(this);mClearBtn.setOnClickListener(this);// 注册选择事件mStandardRg.setOnCheckedChangeListener(this);// 历史记录相关mHistoryIb.setOnClickListener(this);}@Overridepublic void onClick(View v) {int id = v.getId();switch (id) {case R.id.btn_cala:// 计算逻辑// 获取身高输入框数据String heightStr = mHeightInputEt.getText().toString().trim();// 判断身高输入框数据是否为空if ("".equals(heightStr) || heightStr.length() == 0) {Toast.makeText(this, getResources().getString(R.string.tip1), 0).show();} else {try {// 将String类型转化成Double类型height = Double.valueOf(heightStr);// 对身高数据范围进行判断(100.0~200.0)if (height < 100.0 || height > 200.0) {Toast.makeText(this,getResources().getString(R.string.height_round),Toast.LENGTH_SHORT).show();} else {String weightStr = mWeightInputEt.getText().toString().trim();// 体重数据非空判断if ("".equals(weightStr) || weightStr.length() == 0) {Toast.makeText(this,getResources().getString(R.string.tip3),Toast.LENGTH_SHORT).show();} else {try {weight = Double.valueOf(weightStr);// 体重数据范围判断(30.0~150.0)if (weight < 30.0 || weight > 150.0) {Toast.makeText(this,getResources().getString(R.string.weight_round),Toast.LENGTH_SHORT).show();} else {// 计算bmi值calaBmi(mCurrentStandard);// 隐藏计算按钮(GONE),显示结果布局(VISIBLE)setViewVisible(false);}} catch (Exception e) {Toast.makeText(this,getResources().getString(R.string.tip2),Toast.LENGTH_SHORT).show();}}}} catch (Exception e) {Toast.makeText(this,getResources().getString(R.string.tip2),Toast.LENGTH_SHORT).show();}}break;case R.id.btn_clear:// 清除setViewVisible(true);break;case R.id.ib_history:// 跳转到历史记录界面Intent intent = new Intent(MainActivity.this,HistoryRecordActivity.class);startActivity(intent);break;}}/*** 计算bmi值*/private void calaBmi(int standard) {// height/100.0 cm换算成mheight = height / 100.0;bmi = weight / (height * height);if (standard == WHO_STANDARD) {if (bmi < 18.5) {state = states[0];state_imageId = state_imageIds[0];} else if (bmi >= 18.5 && bmi <= 24.9) {state = states[1];state_imageId = state_imageIds[1];} else if (bmi > 24.9 && bmi <= 29.9) {state = states[2];state_imageId = state_imageIds[2];} else if (bmi > 29.9 && bmi <= 34.9) {state = states[3];state_imageId = state_imageIds[3];} else if (bmi > 34.9 && bmi <= 39.9) {state = states[4];state_imageId = state_imageIds[4];} else {state = states[5];state_imageId = state_imageIds[5];}} else {if (bmi < 18.5) {state = states[0];state_imageId = state_imageIds[0];} else if (bmi >= 18.5 && bmi <= 22.9) {state = states[1];state_imageId = state_imageIds[1];} else if (bmi > 22.9 && bmi <= 24.9) {state = states[2];state_imageId = state_imageIds[2];} else if (bmi > 24.9 && bmi <= 29.9) {state = states[3];state_imageId = state_imageIds[3];} else if (bmi > 29.9 && bmi <= 39.9) {state = states[4];state_imageId = state_imageIds[4];} else {state = states[5];state_imageId = state_imageIds[5];}}mStateIv.setImageResource(state_imageId);// 讲计算结果插入数据库Bmi bmiObj = new Bmi();bmiObj.setHeigth(Double.valueOf(DataUtil.getData(height * 100.0)));bmiObj.setWeigth(Double.valueOf(DataUtil.getData(weight)));bmiObj.setBmiNum(Double.valueOf(DataUtil.getData(bmi)));bmiObj.setBmiState(state);bmiObj.setStateIconId(state_imageId + "");// 当前系统时间(单位:毫秒)bmiObj.setCalaTime(System.currentTimeMillis());<span style="color:#ff0000;">insertBmi(bmiObj);</span>}/*** 控制计算按钮与结果布局的显示与隐藏* * @param visible*/private void setViewVisible(boolean visible) {if (visible) {mCalaBtn.setVisibility(View.VISIBLE);mResultLl.setVisibility(View.GONE);// 清空数据mWeightBmiTv.setText("");mWeightStateTv.setText("");mHeightInputEt.setText("");mWeightInputEt.setText("");height = 0.0;weight = 0.0;} else {// 获得焦点mHeightInputEt.requestFocus();// 格式化数据的类mCalaBtn.setVisibility(View.GONE);mResultLl.setVisibility(View.VISIBLE);DecimalFormat format = new DecimalFormat("0.0");mWeightBmiTv.setText(weightBmi + format.format(bmi));mWeightStateTv.setText(weightState + state);}}@Overridepublic void onCheckedChanged(RadioGroup rg, int arg1) {int id = rg.getCheckedRadioButtonId();switch (id) {case R.id.rb_who:// 选中Who单选按钮mCurrentStandard = WHO_STANDARD;break;case R.id.rb_area:// 选中亚洲单选按钮mCurrentStandard = AREA_STANDARD;break;default:mCurrentStandard = WHO_STANDARD;break;}}@Overrideprotected void onResume() {super.onResume();// 获取当前用户选择的标准sp = this.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);mCurrentStandard = sp.getInt("standard", WHO_STANDARD);// 根据用户上次选择的标准初始化单选框的选择状态switch (mCurrentStandard) {case WHO_STANDARD:mWhoStandardRb.setChecked(true);mAreaStandardRb.setChecked(false);break;case AREA_STANDARD:mWhoStandardRb.setChecked(false);mAreaStandardRb.setChecked(true);break;default:mWhoStandardRb.setChecked(true);mAreaStandardRb.setChecked(false);break;}}@Overrideprotected void onPause() {super.onPause();// 保存当前用户选择的标准sp = this.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);Editor editor = sp.edit();editor.putInt("standard", mCurrentStandard);editor.commit();}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {// 监听用户按键,如果按回退键,退出程序if (keyCode == KeyEvent.KEYCODE_BACK) {// 获得对话框标题与提示消息String title = getResources().getString(R.string.back);String message = getResources().getString(R.string.back_message);DialogUtil.showDialog(this, title, message,new OnClickOkListener() {@Overridepublic void onClick(View view) {// 退出程序MainActivity.this.finish();}});}return true;}<span style="color:#ff0000;">@Overrideprotected void onDestroy() {super.onDestroy();// 停止数据服务的方法stopDataService();}</span><span style="color:#ff0000;">/*** 开启数据服务的方法*/private void startDataService() {// 启动数据服务---startintent = new Intent();intent.setAction(DataService.SERVICE_ACTION);intent.setClass(this, DataService.class);startService(intent);// 启动数据服务---end}/*** 停止数据服务的方法*/private void stopDataService() {intent = new Intent();intent.setAction(DataService.SERVICE_ACTION);intent.setClass(this, DataService.class);stopService(intent);}/*** 发命令给数据服务,执行插手数据功能* * @param bmiObj*            要插入的Bmi数据对象*/private void insertBmi(Bmi bmiObj) {// 发送插入数据命令给数据服务,执行插入数据功能---startintent.putExtra(DataService.COMMAND, DataService.INSERT);intent.putExtra(DataService.KEY_BMI, bmiObj);startService(intent);// 发送插入数据命令给数据服务,执行插入数据功能---end}</span>
}

step5:修改HistoryRecordActivity历史记录列表相对应代码(红色字体为修改部分)

package com.kedi.bmi.ui;import java.util.List;import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;import com.kedi.bmi.R;
import com.kedi.bmi.adapter.HistoryRecordAdapter;
import com.kedi.bmi.listener.OnClickOkListener;
import com.kedi.bmi.model.Bmi;
import com.kedi.bmi.service.DataService;
import com.kedi.bmi.utils.DialogUtil;/*** 历史计算记录Activity类* * @author 科弟* */
public class HistoryRecordActivity extends Activity implements OnClickListener,OnItemLongClickListener {private LinearLayout mHistoryLl;// 历史记录布局private TextView mEmptyTv;// 当历史列表为空时,显示该文本提示private ListView mHistoryLv;// 历史记录列表视图private HistoryRecordAdapter mAdapter;// 数据适配器private List<Bmi> mDatas;// 数据集合private ImageButton mBackIb;// 回退按钮private ImageButton mClearIb;// 清空按钮<span style="color:#ff0000;">// 数据服务相关Intentprivate Intent intent;// 广播接送者private DataBroadCastReceiver mReceiver;</span>@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 取消系统默认标题栏requestWindowFeature(Window.FEATURE_NO_TITLE);// 关联XML布局界面setContentView(R.layout.activity_history_record);// 初始化视图的方法initView();// 注册点击事件监听器setListener();<span style="color:#ff0000;">// 配置数据服务configDataService();// 注册DataBroadCastReceiver广播接收者registerDataBroadCastReceiver();// 获取所有历史记录getBmis();</span>}/*** 初始化视图的方法*/private void initView() {mHistoryLl = (LinearLayout) this.findViewById(R.id.ll_history);mEmptyTv = (TextView) this.findViewById(R.id.tv_empty);mHistoryLv = (ListView) this.findViewById(R.id.lv_history);mBackIb = (ImageButton) this.findViewById(R.id.ib_back);mClearIb = (ImageButton) this.findViewById(R.id.ib_clear);}/*** 注册点击事件监听器*/private void setListener() {mBackIb.setOnClickListener(this);mClearIb.setOnClickListener(this);// 注册ListView列表条目长按事件监听器mHistoryLv.setOnItemLongClickListener(this);}@Overridepublic void onClick(View v) {int id = v.getId();switch (id) {case R.id.ib_back:// 销毁当前Activityfinish();break;case R.id.ib_clear:// 弹出二次确认对话框// 获得对话框标题与提示消息String title = getResources().getString(R.string.clear1);String message = getResources().getString(R.string.clear1_message);if (mDatas != null && mDatas.size() > 0) {DialogUtil.showDialog(this, title, message,new OnClickOkListener() {@Overridepublic void onClick(View view) {// 清空所有历史数据deleteBmis();}});} else {Toast.makeText(this, getResources().getString(R.string.empty),Toast.LENGTH_SHORT).show();}break;}}@Overridepublic boolean onItemLongClick(AdapterView<?> adapterView, View view,final int position, long arg3) {// 弹出二次确认对话框// 获得对话框标题与提示消息String title = getResources().getString(R.string.delete);String message = getResources().getString(R.string.delete_message);DialogUtil.showDialog(this, title, message, new OnClickOkListener() {@Overridepublic void onClick(View view) {// 删除当前条目deleteBmi(position);}});return false;}<span style="color:#ff0000;">/*** 配置数据服务*/private void configDataService() {intent = new Intent();intent.setAction(DataService.SERVICE_ACTION);intent.setClass(this, DataService.class);}/*** 发送查询命令到数据服务,获取所有的Bmi数据*/private void getBmis() {intent.putExtra(DataService.COMMAND, DataService.QUERY);startService(intent);}</span>/*** 清空所有历史数据的方法*/private void deleteBmis() {<span style="color:#ff0000;">// 清空数据库deleteBmisDB();</span>// 清空内存集合mDatas.clear();// 刷新界面mAdapter.notifyDataSetChanged();// 显示空文本提示,隐藏历史列表布局mHistoryLl.setVisibility(View.GONE);mEmptyTv.setVisibility(View.VISIBLE);}/*** 删除当前条目的方法* * @param position*/private void deleteBmi(int position) {// 删除当前条目<span style="color:#ff0000;">// 删除数据库对应位置对象对应Id的数据记录deleteBmiDB(mDatas.get(position));</span>// 删除内存集合中对应位置的数据mDatas.remove(position);// 刷新界面mAdapter.notifyDataSetChanged();if (mDatas.size() <= 0) {// 显示空文本提示,隐藏历史列表布局mHistoryLl.setVisibility(View.GONE);mEmptyTv.setVisibility(View.VISIBLE);} else {// 隐藏空文本提示,显示历史列表布局mHistoryLl.setVisibility(View.VISIBLE);mEmptyTv.setVisibility(View.GONE);}}<span style="color:#ff0000;">/*** 清空数据库*/private void deleteBmisDB() {// 清空数据库,给数据服务发送清空命令,执行清空任务intent.putExtra(DataService.COMMAND, DataService.DELETE_ALL);startService(intent);}/*** 删除数据库当前条目*/private void deleteBmiDB(Bmi bmi) {// 删除数据库当前条目,给数据服务发送删除当前条目命令,执行删除当前条目任务intent.putExtra(DataService.COMMAND, DataService.DELETE_ITEM);intent.putExtra(DataService.KEY_BMI, bmi);startService(intent);}</span><span style="color:#ff0000;">/*** 接收从数据服务发送的广播* * @author 科弟* */class DataBroadCastReceiver extends BroadcastReceiver {// 接收广播的Action@SuppressWarnings("unchecked")@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (DataService.RECEIVER_ACTION.equals(action)) {mDatas = (List<Bmi>) intent.getSerializableExtra(DataService.KEY_BMIS);if (mDatas != null && mDatas.size() > 0) {// 隐藏空文本提示,显示历史列表布局mHistoryLl.setVisibility(View.VISIBLE);mEmptyTv.setVisibility(View.GONE);mAdapter = new HistoryRecordAdapter(HistoryRecordActivity.this, mDatas);mHistoryLv.setAdapter(mAdapter);} else {// 显示空文本提示,隐藏历史列表布局mHistoryLl.setVisibility(View.GONE);mEmptyTv.setVisibility(View.VISIBLE);}}}}/*** 注册DataBroadCastReceiver广播接收者*/private void registerDataBroadCastReceiver() {mReceiver = new DataBroadCastReceiver();IntentFilter filter = new IntentFilter(DataService.RECEIVER_ACTION);registerReceiver(mReceiver, filter);}/*** 反注册(销毁)DataBroadCastReceiver广播接收者*/private void unRegisterDataBroadCastReceiver() {if (mReceiver != null) {unregisterReceiver(mReceiver);}}</span><pre name="code" class="java"><span style="font-family: Arial, Helvetica, sans-serif;">             @Override</span>
<span style="font-family: Arial, Helvetica, sans-serif;">              protected void onDestroy() {</span>
     super.onDestroy();// 反注册(销毁)DataBroadCastReceiver广播接收者unRegisterDataBroadCastReceiver();}}

其他功能部分没有改变,可在V3.0的基础上修改,也可将V3.0中未改变的部分直接移植到V4.0项目中。

结语

  V4.0囊括了Android中的四大组件中的三个组件,SQLite数据库等核心技术,希望能让大家对Activity,Service,BroadcastReceiver,SQLite数据库的有更具实战意义的理解!

【BMI指数计算器V4.0】项目实战相关推荐

  1. 【BMI指数计算器V3.0】项目实战

    [BMI指数计算器V3.0]项目实战震撼发布,欢迎前来交流~~~,如果是刚来的朋友可以先从 [BMI指数计算器V1.0]项目实战,[BMI指数计算器V2.0]项目实战开始,这样循序渐进更能感受到每一个 ...

  2. 【BMI指数计算器V2.0】项目实战

    [BMI指数计算器V2.0]是建立在[BMI指数计算器V1.0]的基础上进行功能的增加,以版本迭代的方式循序渐进的进行Android核心技术的练习. 更新列表: 1.BMI计算标准选择 2.体重状态表 ...

  3. 【BMI指数计算器V1.0】项目实战

    项目背景         BMI指数(即身体质量指数,简称体质指数又称体重,英文为Body Mass Index,简称BMI),是用体重公斤数除以身高米数平方得出的数字,是目前国际上常用的衡量人体胖瘦 ...

  4. 如何用C语言和Python编写一个BMI指数计算器

    写在前面   前些日子在学习C语言和Python的循环语句的时候,我心血来潮,想编写一个实用性较高的程序.想来想去,我决定编写一个BMI指数计算器.接下来,我将分享一下我编写这个程序的过程,希望给大家 ...

  5. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-11项目日志解决方案

    本文目录 1. Net下日志记录 2. NLog的使用     2.1 添加nuget引用NLog.Web.AspNetCore     2.2 配置文件设置     2.3 依赖配置及调用     ...

  6. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-10项目各种全局帮助类

    本文目录 1.  前沿 2.CacheHelper基于Microsoft.Extensions.Caching.Memory封装 3.XmlHelper快速操作xml文档 4.Serializatio ...

  7. 使用Python语言实现Bmi指数计算器

    使用Python3.7实现Bmi指数计算器 使用Python中界面编程来实现Bmi指数计算器 1使用tkinter实现bmi指数计算器 使用Python中界面编程来实现Bmi指数计算器 1使用tkin ...

  8. js制作bmi指数计算器代码

    js制作bmi指数计算器代码,js实现bmi指数计算代码教程如下: 1.输入体重 2.输入身高 计算结果:计算出体重指数 js实现代码: function setKeyup(obj) {if (!ob ...

  9. vue3.0项目实战 - ElementUI框架版

    系列文章目录 第一章 论vue3.0和vue2.0区别之编程方式及例子详解 第二章 同一台电脑 实现 vue-cli2和vue-cli3同时并存 及 常见命令 第三章 vue3.0项目实战 - Ele ...

最新文章

  1. 高通研发VR软件进军医疗领域,帮助医生诊断中风病患
  2. 【转】MySQL实现Oracle里的 rank()over(ORDER BY) 功能
  3. 媒体查询常用屏幕分辨率参数
  4. oracle分区exchange,oracle 分区表exchange原理
  5. 电商促销插画风PSD分层模板,直击底价!吸睛容情!
  6. jQuery菜鸟总结
  7. protobuf 安装_Beego 安装时 一直无响应(443)怎么办
  8. linux device attr,DEVICE_ATTR的使用
  9. 欧姆龙plc学习笔记(八)(上传nb程序)
  10. composer 安装php endroid/qrcode二维码应用,二维码里面添加logo
  11. JInternalFrame For JTabbedPane 测试
  12. 软件测试邻居集成,软件测试之集成测试(ppt-3).ppt
  13. hive3.0使用问题小记
  14. 计算机内部可以用哪两种处理器封装类型,电脑CPU处理器封装形式大盘点
  15. 小朋友学数学(22):三角函数
  16. MetCoin 元宇宙是什么?可以免费挖吗?
  17. yolov3网络(DarkNet53)结构详解以及Pytorch代码实现
  18. html页面传递list参数,thinkphp中html:list标签传递多个参数实例,thinkphplist_PHP教程...
  19. Jmeter - webSocket 压力测试笔记
  20. 中国软件行业协会成立25周年庆典 《程序员》荣获杰出传媒奖

热门文章

  1. 同时导出多个excel,并且一个excel中包含多个sheet
  2. GAMES101蒙特卡洛光线追踪及Assignment7
  3. Python 与 数学 【1】
  4. Vue框架学习(七)
  5. 江西省职业院校技能大赛中职组网络安全竞赛之Linux操作系统渗透测试
  6. 思科2960导出系统
  7. myBase Desktop 6.5.1 无限期试用
  8. python 爬虫 教务系统模拟登陆 并下载课表
  9. 人为什么会参与活动?
  10. 实达已经不是那个实达,而叶成辉还是那个叶成辉