开发比较大规模的软件的思路:创建工程-搭建工程框架-界面设计-基类设计-逻辑设计-调试-上传
一:搭建工程框架
秘密需要实现的功能如下:
1.发送验证码
2.输入手机号和验证码登录
3.显示朋友圈
4.点击某条朋友圈进入评论列表
5.发表评论
6.发表朋友圈
二:基类设计
1.要联网因此要指定一个网络通讯基类
网络请求是一个耗时动作,因此使用AsyncTask,在doInBackground处理网络请求,在onPostExecute处理doInBackground返回的数据
并且创建两个回调接口
一个是成功返回时的SuccessCallback,编写一个void onSuccess(String result)方法,
一个是失败时的FailCallback,编写一个void onFail()方法
与服务器交互时常使用的读写数据类和方法有:
StringBuffer的append(), BufferedWriter的write(),flush(), BufferedReader的readLine(), 因此IO很重要
在onPostExecute中,如果传入数据成功,则调用SuccessCallback的onSuccess(result)把返回值传入onSuccess中,
否则,调用onFail(),告诉调用者网络请求失败。
public class NetConnection {
public NetConnection(final String url, final HttpMethod method, final SuccessCallback successCallback,
final FailCallback failCallback, final String ... kvs){//String ... 指可以传入多个String
//成员变量在内部类中使用要加final
new AsyncTask<Void,Void,String>(){//异步任务
@Override
protected String doInBackground(Void... params) {
/*
* 设置上传的参数,如?action=getuserinfo&id=123456
*/
StringBuffer buf = new StringBuffer();
for(int i = 0; i < kvs.length; i+=2){
buf.append(kvs[i]).append("=").append(kvs[i+1]).append("&");
}
try {
URLConnection uc;
/*
* 提交数据给服务器
*/
switch (method) {
case Post:
uc = new URL(url).openConnection();
uc.setDoOutput(true);//往服务端输出
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(uc.getOutputStream(), Config.CHARSET));
out.write(buf.toString());//注意write写到内存中,要用flush来输出
out.flush();
break;
default:
uc = new URL(url+"?"+buf.toString()).openConnection();
break;
}
System.out.println("Request url:"+uc.getURL());
System.out.println("Request data:"+buf);
/*
* 读取服务器返回的数据
*/
BufferedReader in = new BufferedReader
(new InputStreamReader(uc.getInputStream(),Config.CHARSET));
String line;
StringBuffer result = new StringBuffer();
while((line = in.readLine()) != null){
result.append(line);
}
System.out.println("Result:" + result.toString());
return result.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//doInBackground的数据会传入此
@Override
protected void onPostExecute(String result) {
if(result!=null){
if(successCallback != null){
successCallback.onSuccess(result);
}
}else {
if(failCallback != null){
failCallback.onFail();
}
}
super.onPostExecute(result);
}
}.execute();//在主线程执行AsyncTask
}
public static interface SuccessCallback{
void onSuccess(String result);
}
public static interface FailCallback{
void onFail();
}
}
代码如下:
2.发送验证码基类
发送验证码要网络请求,因此需要调用网络通讯基类,在后面你会发现,java封装的力量,这个网络通讯基类让我们非常方便的实现了网络请求
public class GetCode {
public GetCode(String phone, final SuccessCallback successCallback, final FailCallback failCallback){
new NetConnection(Config.SERVER_URL, HttpMethod.Post, new NetConnection.SuccessCallback() {
@Override
public void onSuccess(String result) {
System.out.println("Result in GetCode:" + result.toString());
try {
//没有传进result,导致被catch了
JSONObject obj = new JSONObject(result);
System.out.println("Obj" + obj.getInt(Config.KEY_STATUS));
switch (obj.getInt(Config.KEY_STATUS)) {
case Config.RESULT_STATUS_SUCCESS:
if (successCallback != null) {
successCallback.onSuccess();
}
break;
default:
if (failCallback != null) {
failCallback.onFail();
}
}
} catch (Exception e) {
System.out.println("ObjError");
e.printStackTrace();
if (failCallback != null) {
failCallback.onFail();
}
}
}
}, new NetConnection.FailCallback() {
@Override
public void onFail() {
if(failCallback != null){
failCallback.onFail();
}
}
}, Config.KEY_ACTION, Config.ACTION_GET_CODE, Config.KEY_PHONE_NUM, phone);
}
public static interface SuccessCallback{
void onSuccess();
}
public static interface FailCallback{
void onFail();
}
}
因为接下来的基类设计思想都大致一样,都是调用网络请求基类,使用回调机制告诉调用者成功与否,调用成功处理返回的数据
,因此就不再贴出此类代码。
如此还要制定
3.登录基类
4.获取手机联系人基类
5.获取朋友圈基类
6.获取评论基类
7.发表评论基类
8.发布朋友圈基类
有如下几点需要注意:
(1).当返回的JSON数组中内含JSON数组,则需要如下获取:
JSONObject obj = new JSONObject(result);
JSONArray msgJSONArray = obj.getJSONArray(Config.KEY_TIMELINE);
(2).内部类调用局部变量,局部变量必须为final
三:逻辑设计
1.登陆界面逻辑
登陆后,应该缓存token和phone,缓存token是为了判定token过期之后直接跳转回登陆界面,就相当微信长时间不上线,就会自动注销,回到登陆界面。
2.加载朋友圈界面逻辑
加载朋友圈之前,要加载联系人数据
timeline是一个listview,在此使用BaseAdapter
public class AtyTimelineMessageListAdapter extends BaseAdapter {
private List<Message> timeline = new ArrayList<Message>();
private Context context = null;
public AtyTimelineMessageListAdapter(Context context){
this.context = context;
}
public Context getContext(){
return context;
}
//获得listView的个数
@Override
public int getCount() {
return timeline.size();
}
//获得当前item的位置或者称为ID
@Override
public Object getItem(int position) {
return timeline.get(position);
}
//????
@Override
public long getItemId(int position) {
return position;
}
//添加数据
public void addAll(List<Message> data){
timeline.addAll(data);
notifyDataSetChanged();
}
//清空数据
public void clear(){
timeline.clear();
notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.aty_timeline_list_cell, null);
convertView.setTag(new ListCell((TextView) convertView.findViewById(R.id.tvCellLabel)));
}
Message msg = (Message) getItem(position);
ListCell lc = (ListCell) convertView.getTag();
lc.geTextView().setText(msg.getMsg());
return convertView;
}
//实际为ViewBuilder,后期更正
private static class ListCell{
private TextView tvCellLabel;
public ListCell(TextView tvCellLabel){
this.tvCellLabel = tvCellLabel;
}
public TextView geTextView(){
return tvCellLabel;
}
}
}
3.获取朋友圈评论列表和发表评论
也是一个listview,也使用baseAdapter
注意:
发表评论,传入的phone应该是你登录时缓存的phone,而不是从timeline跳转过来传过来的phone
4.发布朋友圈
注意:
发布朋友圈,传入的phone应该是你登录时缓存的phone,而不是从timeline跳转过来传过来的phone
四:多语言配置
新建strings,把原来strings中copy过来,对应翻译成中文就行了