7. 能否讲讲你用过的adapter?
[img]http://dl2.iteye.com/upload/attachment/0088/4942/f94d5597-d218-328f-b2a2-3d6abcfda126.png[/img]
cursorAdapter 取文件浏览器FileListCursorAdapter的例子
ArrayAdapter
在构造方法里面绑定数据源,然后在getView方法里面将数据绑定UI就好
expandableListView是可扩展子项的listView
但是这种空间只适用两层结构,用起来也比较麻烦,我个人感觉适用的范围比较窄。
要想做出类似于电脑上资源管理器的TreeView
应该的思路是
1.利用多叉树结构保存数据
2.使用listView,不同的层次有不同的pading,根据父子节点关系,控制层次开关。
TreeView
8. 已经发布了软件版本A,使用sqlite存储用户数据其DB version为1包含某张表T1,则其后需要发布版本B,在版本A的T1表结构的基础上又增加了2个新的字段,则能否在保存用户已经安装的版本A的数据的前提下,更新安装新版本B?
9. 你怎么看待在android上面应用MVC框架,是否有必要抽象独立于activity的C?
通过查看Android中的Launcher的源码,大家会发现其中会有LauncherModel.java,Workspace.java,Launcher.java。
其中LauncherModel为辅助文件封装了许多对数据库的操作(对应MVC中的Model);Workspace为一个抽象的桌面,将应用显示在用户面前,与用户进行交互(对应MVC中的View);Launcher是主要的Activity,里面有很多对用户的操作进行处理,并且将结果反馈在Workspace中(对应MVC中的Controller)。
1) 视图层(View):一般采用XML文件进行界面的描述,使用的时候可以非常方便的引入。当然,如何你对Android了解的比较的多了话,就一定可以想到在Android中也可以使用JavaScript+HTML等的方式作为View层,当然这里需要进行Java和JavaScript之间的通信,幸运的是,Android提供了它们之间非常方便的通信实现。
2) 控制层(Controller):Android的控制层的重任通常落在了众多的Acitvity的肩上,这句话也就暗含了不要在Acitivity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3) 模型层(Model):对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。
[img]http://dl2.iteye.com/upload/attachment/0088/4942/f94d5597-d218-328f-b2a2-3d6abcfda126.png[/img]
cursorAdapter 取文件浏览器FileListCursorAdapter的例子
public class FileListCursorAdapter extends CursorAdapter {
//将数据绑定到UI
@Override
public void bindView(View view, Context context, Cursor cursor) {
FileInfo fileInfo = getFileItem(cursor.getPosition());//根据游标当前的指向,获取数据
//初始化UI
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mFactory.inflate(R.layout.category_file_browser_item, parent, false);
}
//可以切换游标
@Override
public void changeCursor(Cursor cursor) {
mFileNameList.clear();
super.changeCursor(cursor);
}
ArrayAdapter
在构造方法里面绑定数据源,然后在getView方法里面将数据绑定UI就好
ArrayAdapter(Context context, int resource)
ArrayAdapter(Context context, int resource, int textViewResourceId)
ArrayAdapter(Context context, int resource, T[] objects)
ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects)
ArrayAdapter(Context context, int resource, List<T> objects)
ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects)
//
@Override
public View getView(int position, View convertView, ViewGroup parent) {
expandableListView是可扩展子项的listView
但是这种空间只适用两层结构,用起来也比较麻烦,我个人感觉适用的范围比较窄。
要想做出类似于电脑上资源管理器的TreeView
应该的思路是
1.利用多叉树结构保存数据
2.使用listView,不同的层次有不同的pading,根据父子节点关系,控制层次开关。
class ProgressAdapter extends ArrayAdapter<FileInfo> {
private int resourceId;
public ProgressAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
resourceId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d(TAG, "position " + position + " " + convertView);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resourceId, null);
} else {
}
FileInfo fileInfo = mSelectedFileList.get(position);
VO vo = volist.get(fileInfo.filePath);
if (vo == null) {
vo = new VO(fileInfo);
volist.put(vo.filePath, vo);
Log.d(TAG, "position " + fileInfo);
// progressTxt.put(vo.filePath, txt_progress);
}
ImageView img_progress_icon = (ImageView) convertView.findViewById(R.id.img_progress_icon);
img_progress_icon.setImageResource(FileIconHelper.getFileIcon(Util.getExtFromFilename(vo.filePath)));
TextView txt_progress_fileinfo = (TextView) convertView.findViewById(R.id.txt_progress_fileinfo);
txt_progress_fileinfo.setText(mContext.getString(R.string.progress_fileinfo, vo.fileName, vo.fileSize / (1024 * 1024)));
ProgressBar progress_bar = (ProgressBar) convertView.findViewById(R.id.progress_bar);
progress_bar.setProgress(vo.progress);
TextView txt_progress = (TextView) convertView.findViewById(R.id.txt_progress);
txt_progress.setText(vo.progress + "%");
return convertView;
}
@Override
public int getCount() {
Log.d(TAG, "getCount ===== " + mSelectedFileList.size());
return mSelectedFileList.size();
}
@Override
public FileInfo getItem(int position) {
return mSelectedFileList.get(position);
}
}
//更新进度
public void updateProgress(String src, float f) {
int value = f > 1 ? 100 : (int) (f * 100);
Message message = new Message();
message.obj = src;
message.what = 1;
message.arg1 = value;
mHandler.sendMessage(message);
}
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
VO vo = volist.get(msg.obj);
vo.progress = msg.arg1;
volist.remove(vo.filePath);
volist.put(vo.filePath, vo);
/*
* ProgressBar progressBar = progresses.get(msg.obj);
* progressBar.setProgress(msg.arg1); TextView textView =
* progressTxt.get(msg.obj); textView.setText(msg.arg1 + "%");
* progressBar.postInvalidate(); textView.postInvalidate();
*/
mAdapter.notifyDataSetChanged();
Log.d(TAG, " updateProgress " + msg.obj + " " + msg.arg1 + " " + vo.progress);
}
super.handleMessage(msg);
}
};
TreeView
//从根节点初始化朵叉树,要用到迭代
HashMap<String, DirTreeNode> map = new HashMap<String, DirTreeNode>();
private void initDirData() {
map.clear();
rootNode = new DirTreeNode(ROOT_TREE_DIR, 0, null);
map.put(ROOT_TREE_DIR, rootNode);
PDFOutlineElement rootElement = new PDFOutlineElement(rootNode.mId + "", rootNode.mNodePath, false, true, null, rootNode.mLevel, true);
// mPdfOutlinesCount.add(rootElement);
// mPdfOutlines.add(rootElement);
File[] listFiles = rootNode.mFile.listFiles();
initFiles(listFiles, rootNode);
// Log.d(TAG, "alllllll " + Arrays.toString(map.keySet().toArray()));
}
private void initFiles(File[] listFiles, DirTreeNode fatherNode) {
if (listFiles != null) {
for (File f : listFiles) {
synchronized (this) {
if (f.isDirectory()) {
DirTreeNode dt = null;
if (!map.containsKey(f.getAbsolutePath())) {
String absolutePath = f.getAbsolutePath();
dt = new DirTreeNode(absolutePath, map.size() + 1, fatherNode);
String childPath = absolutePath.replace(ROOT_TREE_DIR, "");
int count = 0;
for (int i = 0; i < childPath.length(); i++) {
char c = childPath.charAt(i);
if (c == File.separatorChar) {
count++;
}
}
// Log.d(TAG, childPath);
dt.mLevel = count + 1;
Log.d(TAG, " new DirNode ---- " + f.getAbsolutePath() + " level " + dt.mLevel + " id " + dt.mId);
map.put(f.getAbsolutePath(), dt);
PDFOutlineElement element = new PDFOutlineElement(dt.mId + "", dt.mNodePath, dt.mFatherNode != null, dt.mHasChild,
dt.mFatherNode.mId + "", dt.mLevel, true);
mPdfOutlinesCount.add(element);
mPdfOutlines.add(element);
Log.d(TAG, element + "");
if (f.listFiles() != null) {
initFiles(f.listFiles(), dt);
}
}
}
}
}
}
}
class DirTreeNode {
String mNodePath = null;
DirTreeNode mFatherNode = null;
private File mFile;
int mId = 0;
int mLevel = 0;
boolean mHasChild = false;
public DirTreeNode(String path, Integer id, DirTreeNode father) {
mFatherNode = father;
mNodePath = path;
mFile = new File(path);
if (father == null) {
mLevel = 0;
} else {
mLevel = father.mLevel + 1;
}
mId = id;
File[] listFiles = mFile.listFiles();
for (File f : listFiles) {
if (f.isDirectory()) {
mHasChild = true;
break;
}
}
}
@Override
public String toString() {
return "DirTreeNode [mNodePath=" + mNodePath + ", mFatherNode=" + mFatherNode + ", mFile=" + mFile + ", mId=" + mId + ", mLevel=" + mLevel
+ ", mHasChild=" + mHasChild + "]";
}
}
class PDFOutlineElement implements Comparable {
private String id;
private String outlineTitle;
private boolean mhasParent;
private boolean mhasChild;
private String parent;
private int level;
//适配器
private class TreeViewAdapter extends ArrayAdapter {
public TreeViewAdapter(Context context, int textViewResourceId, List objects) {
super(context, textViewResourceId, objects);
mInflater = LayoutInflater.from(context);
mfilelist = objects;
mIconCollapse = BitmapFactory.decodeResource(context.getResources(), R.drawable.letou_manager_copy_collapse);
mIconExpand = BitmapFactory.decodeResource(context.getResources(), R.drawable.letou_manager_copy_expand);
}
private LayoutInflater mInflater;
private List<PDFOutlineElement> mfilelist;
private Bitmap mIconCollapse;
private Bitmap mIconExpand;
public int getCount() {
return mfilelist.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.outline, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
int level = mfilelist.get(position).getLevel();
holder.icon.setPadding(25 * (level > 0 ? (level - 1) : 0), holder.icon.getPaddingTop(), 0, holder.icon.getPaddingBottom());
String stringPath = mfilelist.get(position).getOutlineTitle();
boolean isRoot = stringPath.equalsIgnoreCase(ROOT_TREE_DIR);
if (isRoot) {
// convertView.setVisibility(View.GONE);
// return convertView;
}
int lastIndexOf = stringPath.lastIndexOf(File.separatorChar);
if (lastIndexOf != -1) {
stringPath = stringPath.substring(lastIndexOf + 1);
}
holder.text.setText(isRoot ? ROOT_TREE_DIR : stringPath);
if (mfilelist.get(position).isMhasChild() && (mfilelist.get(position).isExpanded() == false)) {
holder.icon.setImageBitmap(mIconCollapse);
holder.icon.setVisibility(View.VISIBLE);
} else if (mfilelist.get(position).isMhasChild() && (mfilelist.get(position).isExpanded() == true)) {
holder.icon.setImageBitmap(mIconExpand);
holder.icon.setVisibility(View.VISIBLE);
} else if (!mfilelist.get(position).isMhasChild()) {
if (isRoot) {
Log.d(TAG, " +++++++++++++++++");
}
holder.icon.setImageBitmap(mIconCollapse);
holder.icon.setVisibility(View.INVISIBLE);
}
holder.icon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mPdfOutlinesCount.get(position).isMhasChild()) {
Toast.makeText(mContext, mPdfOutlinesCount.get(position).getOutlineTitle(), 2000).show();
return;
}
Log.d(TAG, "" + mPdfOutlinesCount.get(position).isExpanded());
if (mPdfOutlinesCount.get(position).isExpanded()) {
mPdfOutlinesCount.get(position).setExpanded(false);
PDFOutlineElement pdfOutlineElement = mPdfOutlinesCount.get(position);
ArrayList<PDFOutlineElement> temp = new ArrayList<PDFOutlineElement>();
for (int i = position + 1; i < mPdfOutlinesCount.size(); i++) {
if (pdfOutlineElement.getLevel() >= mPdfOutlinesCount.get(i).getLevel()) {
break;
}
temp.add(mPdfOutlinesCount.get(i));
}
mPdfOutlinesCount.removeAll(temp);
treeViewAdapter.notifyDataSetChanged();
} else {
mPdfOutlinesCount.get(position).setExpanded(true);
int level = mPdfOutlinesCount.get(position).getLevel();
int nextLevel = level + 1;
Log.d(TAG, "nextLevel " + nextLevel);
for (int i = 0; i < mPdfOutlines.size(); i++) {
PDFOutlineElement pdfOutlineElement = mPdfOutlines.get(mPdfOutlines.size() - i - 1);
int j = 1;
if (pdfOutlineElement.getParent() == null)
continue;
if (mPdfOutlinesCount.get(position).getId().trim().equalsIgnoreCase(pdfOutlineElement.getParent().trim())) {
Log.d(TAG, "pdfOutlineElement.getParent() " + pdfOutlineElement.getParent());
Log.d(TAG, "mPdfOutlinesCount.get(position).getId() " + mPdfOutlinesCount.get(position).getId());
pdfOutlineElement.setLevel(nextLevel);
pdfOutlineElement.setExpanded(false);
mPdfOutlinesCount.add(position + j, pdfOutlineElement);
Log.d(TAG, position + " " + j + " " + pdfOutlineElement);
j++;
}
}
treeViewAdapter.notifyDataSetChanged();
}
}
});
final Integer id = Integer.valueOf(mPdfOutlinesCount.get(position).getId().trim());
if (whichDir != id) {
convertView.setBackgroundColor(Color.BLACK);
}
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "onClick" + id + " " + whichDir);
if (whichDir != id) {
whichDir = Integer.valueOf(mPdfOutlinesCount.get(position).getId().trim());
}
Log.d(TAG, oldView + "");
if (oldView != null) {
oldView.setBackgroundColor(Color.BLACK);
}
v.setBackgroundDrawable(drawableItemBg);
oldView = v;
mTargetDir = mPdfOutlinesCount.get(position).outlineTitle;
updateDestPath();
}
});
return convertView;
}
}
8. 已经发布了软件版本A,使用sqlite存储用户数据其DB version为1包含某张表T1,则其后需要发布版本B,在版本A的T1表结构的基础上又增加了2个新的字段,则能否在保存用户已经安装的版本A的数据的前提下,更新安装新版本B?
1,检测是否需要升级数据库文件。数据库文件版本是由versionCode控制。程序升级时,如果需要升级数据库,则要将versionCode+1。
2,将新数据库文件(存在于apk中),写入SD卡。
3,转移数据。
4,删除原数据库文件,重命名新数据库文件。
5,向新数据库写入当前数据库版本。
9. 你怎么看待在android上面应用MVC框架,是否有必要抽象独立于activity的C?
通过查看Android中的Launcher的源码,大家会发现其中会有LauncherModel.java,Workspace.java,Launcher.java。
其中LauncherModel为辅助文件封装了许多对数据库的操作(对应MVC中的Model);Workspace为一个抽象的桌面,将应用显示在用户面前,与用户进行交互(对应MVC中的View);Launcher是主要的Activity,里面有很多对用户的操作进行处理,并且将结果反馈在Workspace中(对应MVC中的Controller)。
1) 视图层(View):一般采用XML文件进行界面的描述,使用的时候可以非常方便的引入。当然,如何你对Android了解的比较的多了话,就一定可以想到在Android中也可以使用JavaScript+HTML等的方式作为View层,当然这里需要进行Java和JavaScript之间的通信,幸运的是,Android提供了它们之间非常方便的通信实现。
2) 控制层(Controller):Android的控制层的重任通常落在了众多的Acitvity的肩上,这句话也就暗含了不要在Acitivity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3) 模型层(Model):对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。