1. 对话保持的解决方案。
要求:
1、app中使用webview访问具体网站的内容,但是app与服务器的沟通是使用HttpUrlConnection来完成。
2、webview访问时不需要再次登陆,继承app的登陆状态。
对话未保持的现象:、
1、 虽然app已经登录服务器,但是在webview中还是提示需要登录。
2、app下一次对服务器的请求也会失败,提示session过期。
解决方案:
1、获取到HttpUrlConnection中服务器返回的session id。
2、本地保存session id,每次对服务器的请求,手动添加。
3、将此session id设置到持有webview的activity中的CookieManager里。
关键代码:
网络处理类 NetHelper
/**
* 发送登陆请求,并将SESSIONID保存起来
* @param urlPath 登陆请求的地址
* @return 返回的内容
* */
public static String login(String urlPath) {
......省略号......
try {
URL url = new URL(urlPath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//设置请求方式
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
// conn.setReadTimeout(5000);
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream is = conn.getInputStream();
cookList = conn.getHeaderFields().get("Set-Cookie");
if ((sessionId == null) && (cookList != null)) {
for (String value : cookList) {
if ((value != null) && (value.toUpperCase().indexOf(";") > 0)) {
sessionId = value.split(";")[0];
}
}
}
......省略号......
}
}catch (Exception e){
e.printStackTrace();
}
......省略号......
}/**
* 发送一条请求,将内容以字符串返回
* @param urlPath 请求的地址
* @return 返回的内容
* */
public static String request(String urlPath) {
......省略号......
try {
URL url = new URL(urlPath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if(sessionId !=null ){
conn.setRequestProperty("Cookie",sessionId);
}
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
// conn.setReadTimeout(5000);
......省略号......
} catch (Exception e) {
e.printStackTrace();
}
......省略号......
}持有webview的Activity MainActivity
private CookieManager cookieManager;
cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
clearSession();
private void clearSession() {
if (NetHelper.cookList != null) {
cookieManager.removeSessionCookie();
}
}
//在第一次请求的时候,设置一次session即可
private void setSession(String url) {
if (NetHelper.cookList != null) {
String values = NetHelper.cookList.toString();
cookieManager.setCookie(url, values); //设置cookie
CookieSyncManager.getInstance().sync(); //同步
}
}
2. 自定义控件的实现方案
自定义控件的实现方式(详细内容可以参考压缩包中的<自定义控件.pdf>):
1、继承方式
当简单控件不满足需求时,通过继承重写简单控件,实现对控件的定制。
2、组合方式
当单个控件不满足需求时,可以采用多个控件的组合,实现对控件的定制。
3、控件自绘方式
通过继承自view,重写onDraw方法实现。
项目中的具体应用:
1、登录邮箱的自动补全功能实现(纯代码实现布局)。
2、弹窗滚轮的实现(代码加布局文件)
3、TabButton的实现(两种实现方式)
A、 登录邮箱的自动补全功能实现:
效果:
实现原理:
1、继承重写简单控件AutoCompleteTextView
2、编写自定义数据适配器和布局文件,并实现文字变化监听器
3、通过组合方式,实现右侧的删除图标。并根据焦点和文字的变化,动态显示右侧删除图标。
1、通过继承自简单控件AutoCompleteTextView实现帐号自动补全
关键代码:
public class AutoComplete extends AutoCompleteTextView {
private static final String[] emailSuffix = {
"@qq.com", "@163.com", "@126.com", "@gmail.com", "@sina.com", "@hotmail.com",
"@yahoo.cn", "@sohu.com", "@foxmail.com", "@139.com", "@yeah.net", "@vip.qq.com",
"@vip.sina.com"};
......省略号......
//构造函数原型要正确,留给系统调用
public AutoComplete(Context context) {
super(context);
mContext = context;
}
public AutoComplete(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
public void init(ImageView imageView) {
mImageView = imageView;
final MyAdatper adapter = new MyAdatper(mContext);
setAdapter(adapter);
addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if (isTextWatch) {
String input = s.toString();
......省略号......
adapter.clearList(); //注意要清空数据,根据输入的变化,自动生成数据
if (input.length() > 0) {
for (int i = 0; i < emailSuffix.length; ++i) {
adapter.addListData(input + emailSuffix[i]);
}
}
adapter.notifyDataSetChanged();
showDropDown();//该行代码会造成崩溃
}
}
});
//当输入一个字符的时候就开始检测
setThreshold(1);
}
private class ViewHolder {
TextView tv_Text;
}
class MyAdatper extends BaseAdapter implements Filterable {
private List<String> mList;
private Context mContext;
private MyFilter mFilter;
......省略号......
public void clearList() {
mList.clear();
}
public void addListData(String strData) {
mList.add(strData);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder viewHolder;
if (convertView == null) {
view = LayoutIn