Android应用开发之Android开发之规划项目结构的实例
白羽 2018-12-03 来源 :网络 阅读 337 评论 0

摘要:本文将带你了解Android应用开发之Android开发之规划项目结构的实例,希望本文对大家学Android有所帮助。

    本文将带你了解Android应用开发之Android开发之规划项目结构的实例,希望本文对大家学Android有所帮助。


<

规划Android项目结构
1.1建立AndroidLab类库,将与业务无关的逻辑转移到AndroidLab。AndroidLab至少包括五大部分:包名+ acticity,cache,net,ui,utils 。
activity包里面存放的是与业务无关的Activity基类。net包里存放的是网络底层封装。cacahe包里面存放的是缓存数据的图片和图片的相关处理。ui包中存放的是自定义控件utils包中存放的是各种与类无关的功用方法。
将主项目的类分门别类的进行划分,放置在各种包中。
activity:我们按照模块继续划分,将不同模块的Activity划分到不同的包中。adapter:所有的适配器都放在一起entity:所有的实体都放在一起db:SQLite相关逻辑的封装engine:将业务相关的类都放在一起ui:将自定义控件都放在这个包里utils:将所有的公用方法都放在这里interfaces:真正意义上的接口,命名以I作为开头listener:基于Listener的接口,命名以On作为开头
1.2 为Activity定义新的生命周期
可以把onCreate方法拆成三个子方法
initVariables:初始化变量,包括Intent带的数据和Activity内的变量initViews:加载layout布局文件,初始化控件,为控件挂上事件方法loadData:调用MobileAPI获取数据
1.3 统一事件编程模型
只要在一个团队内部达成了协议,决定使用某种事件编程方式,所有开发人员就要按照同样的方式编写代码。
1.4 实体化编程
1.4.1在网络请求中使用实体
一些开发人员不使用实体化编程,在获取MobileAPI网络请求返回的JSON数据时,使用JSONObject或者JSONArray来承载数据,然后把返回的数据当作一个字典,根据键取出响应的值。介绍fastJSON和GSON这种实体化编程的方式.
使用fastJSON如下:
WeatherEntity weatherEntity = JSON.parseObject(content,                        WeatherEntity.class);                WeatherInfo weatherInfo = weatherEntity.getWeatherInfo();                if (weatherInfo != null) {                    tvCity.setText(weatherInfo.getCity());                    tvCityId.setText(weatherInfo.getCityid());                }
使用GSON如下:
Gson gson = new Gson();                WeatherEntity weatherEntity = gson.fromJson(content,                        WeatherEntity.class);                WeatherInfo weatherInfo = weatherEntity.getWeatherInfo();                if (weatherInfo != null) {                    tvCity.setText(weatherInfo.getCity());                    tvCityId.setText(weatherInfo.getCityid());                }
1.4.3 在页面跳转中实现实体
在一个页面中,数据的来源有两种:
调用MobileAPI获取JSON数据从上一个页面传递过来
Activity之间的数据传递一个偷懒的办法是设置一个全局变量,在来源页设置全局变量,在目标页接收全局变量。以下是来源页MainActivity的代码:
Intent intent = new Intent(MainActivity.this,                        LoginActivity.class);                intent.putExtra(AppConstants.Email, "jianqiang.bao@qq.com");                                                 CinemaBean cinema = new CinemaBean();                cinema.setCinemaId("1");                cinema.setCinemaName("星美");                 //使用全局变量的方式传递参数                GlobalVariables.Cinema = cinema;                startActivity(intent);
以下是目标页LoginActivity的代码:
// 使用全局变量的方式传值        CinemaBean cinema = GlobalVariables.Cinema;        if (cinema != null) {            cinemaName = cinema.getCinemaName();        } else {            cinemaName = "";        }
不建议使用全局变量。App一旦被切换到后台,当手机内存不足的时候,就会回收这些全局变量,从而当App再次切换回前台时,再继续使用全局变量,就会因为它们为空而崩溃。如果必须使用全局变量,就一定要把它们序列化到本地。这样即使全局变量为空,也能从本地文件中恢复。
我们使用Intent在页面间来传递数据实体的机制。
首先,在MainActivity中:
Intent intent = new Intent(MainActivity.this,                        LoginNewActivity.class);                intent.putExtra(AppConstants.Email, "jianqiang.bao@qq.com");                                 CinemaBean cinema = new CinemaBean();                cinema.setCinemaId("1");                cinema.setCinemaName("星美");                                 //使用intent上挂可序列化实体的方式传递参数                intent.putExtra(AppConstants.Cinema, cinema);                 startActivity(intent);
其次,目标页LoginActivity要这样写:
CinemaBean cinema = (CinemaBean)getIntent()                .getSerializableExtra(AppConstants.Cinema);        if (cinema != null) {            cinemaName = cinema.getCinemaName();        } else {            cinemaName = "";        }
这里的CinemaBean要实现Serializable接口,支持序列化:
public class CinemaBean implements Serializable {    private static final long serialVersionUID = 1L;     private String cinemaId;    private String cinemaName;     public CinemaBean() {     }     public String getCinemaId() {        return cinemaId;    }     public void setCinemaId(String cinemaId) {        this.cinemaId = cinemaId;    }     public String getCinemaName() {        return cinemaName;    }     public void setCinemaName(String cinemaName) {        this.cinemaName = cinemaName;    } }
1.5 Adapter模版不对Adapter的写法进行规范,就会写出以下的Adapter
很多开发人员都喜欢将Adapter内嵌在Activity中,一般会使用SimpleAdapter
由于没有使用实体,所以一般会把一个字典作为构造函数的参数注入到Adapter中
希望Adapter只有一个编码风格,这样发现了问题也很容易排查。于是要求所有的Adapter都继承自BaseAdapter,从构造函数注入List<自定义实体>这样的数据集合,从而完成ListView的填充工作:
public class CinemaAdapter extends BaseAdapter {    private final ArrayList<cinemabean> cinemaList;    private final AppBaseActivity context;     public CinemaAdapter(ArrayList<cinemabean> cinemaList,            AppBaseActivity context) {        this.cinemaList = cinemaList;        this.context = context;    }     public int getCount() {        return cinemaList.size();    }     public CinemaBean getItem(final int position) {        return cinemaList.get(position);    }     public long getItemId(final int position) {         return position;    }</cinemabean></cinemabean>
对于每个自定义的Adapter,都要实现以下4个方法:
getCount()getItem()getItemId()getView()
此外,还要内置一个Holder嵌套类,用于存放ListView中每一行中的控件。ViewHolder的存在,可以避免频繁创建同一个列表项,从而极大的节省内存,如下:
class Holder {        TextView tvCinemaName;        TextView tvCinemaId;    }
当有很多列表数据时,快速滑动列表会变的很卡,其实就是因为没有ViewHolder机制导致的,正确的写法如下:
public View getView(final int position, View convertView,            final ViewGroup parent) {        final Holder holder;        if (convertView == null) {            holder = new Holder();            convertView = context.getLayoutInflater().inflate(                    R.layout.item_cinemalist, null);            holder.tvCinemaName = (TextView) convertView                    .findViewById(R.id.tvCinemaName);            holder.tvCinemaId = (TextView) convertView                    .findViewById(R.id.tvCinemaId);            convertView.setTag(holder);        } else {            holder = (Holder) convertView.getTag();        }         CinemaBean cinema = cinemaList.get(position);        holder.tvCinemaName.setText(cinema.getCinemaName());        holder.tvCinemaId.setText(cinema.getCinemaId());        return convertView;    }
在Activity中,在使用Adapter的地方,我们按照下面的方式把列表数据传递过去:
@Override    protected void initViews(Bundle savedInstanceState) {        setContentView(R.layout.activity_listdemo);              lvCinemaList = (ListView) findViewById(R.id.lvCinemalist);                 CinemaAdapter adapter = new CinemaAdapter(                cinemaList, ListDemoActivity.this);        lvCinemaList.setAdapter(adapter);        lvCinemaList.setOnItemClickListener(                new AdapterView.OnItemClickListener() {                    @Override                    public void onItemClick(AdapterView<!--?--> parent, View view,                            int position, long id) {                        //do something                    }                });    }
1.6 类型安全转换函数
在每天统计线上崩溃的时候,我们发现因为类型转换不正确导致的崩溃占了很大的比例。于是去检查程序中的所有类型转换,发现主要集中在两个地方:Object类型的对象,substring函数。
对于一个Object类型的对象,我们对其使用字符串操作函数toString,当其为null时就会崩溃。
?1int result = Integer.valueOf(obj.toString());
一旦obj这个对象为空,那么上面这行代码就会直接崩溃,这里的obj,一般是从JSON数据中取出来的,对于MobileAPI返回的JSON数据,我们无法保证其永远不为空。
比较好的做法是编写一个类型安全转换函数convertToInt,实现如下:
public final static int convertToInt(Object value, int defaultValue) {    if (value == null || "".equals(value.toString().trim())) {        return defaultValue;    }    try {        return Integer.valueOf(value.toString());    } catch (Exception e) {        try {            return Double.valueOf(value.toString()).intValue();        } catch (Exception e1) {            return defaultValue;        }    } }
将这个方法放到Utils类下面,每当要把一个Object对象转化成整型时,都使用该方法,就不会崩溃
int result = Utils.convertToInt(obj, 0);
如果长度不够,执行substring函数就会崩溃。Java的substring有两个参数:start和end。
String cityName = "T"; String firstLetter = cityName.substring(1, 2);
对于第一个参数设为0一般没有问题,设置为大于0如上代码就会崩溃,使用substring函数的时候,都要判断start和end两个参数是否越界了,应该这样写:
String cityName = "T";String firstLetter = "";if(cityName.length() > 1){    cityName.substring(1, 2);}
对于MobileAPI返回的数据
首先,不能让App直接崩溃,应该在解析JSON数据的外面包一层try...catch...语句,将截获到的异常在catch中进行处理,比如发送错误日志给服务器。
其次,需要分级对待,例如:
对于那些不需要加工就能直接展示的数据,我们不担心,即使为空页面也就是不显示而已,不会引起逻辑的问题。对于那些很重要的数据,比如涉及支付的金额不能为空的逻辑,这时候就应该弹出提示框提示用户当前服务不可用,并停止接下来的操作。    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!

本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程