做了一个类似电子市场的应用,遇到了很多问题,记下来。

  1. 使用apache的Http包进行网络通信,如果添加了消息头("Accept-Encoding", "gzip,deflate"),那么无论从服务器获取的数据是否经过了gzip,都会对其进行解压缩,那么如果数据本来没有压缩而被解压缩了,就会乱码。设置这个消息头的时候一定要注意。

  2. include,viewStub标签的使用

    先说include标签,include标签的主要作用是复用已经写好的布局文件,但是有局限,因为include标签只能覆盖被引用布局的width,high,margin,weight等基本属性,无法修改引用布局中的子view的属性,它属于一成不变的引用,也不是说不能修改,只能在程序中动态的修改,所以include标签可以用,但不要去强用这个标签,会造成不必要的麻烦

  再说viewStub标签

  他的好处是如果不调用这个对象的inflate方法,那么这个对象就不会被实例化,当你需要这个布局的时候,调用他的inflate方法,就会绘制这个布局,这样能够节省内存。

  疑议:没有inflate前的view和设置他的visible的属性为gone,有没有区别呢?

viewStub的默认属性是invisible,不是gone,通过设置他为visible或者调用他的inflate方法,都可以实现加载这个view,他继承自view,可以在运行时加载,此外他还不同于view设置invisible,view设置为invisible后,该view会被inflate,会占据一定的空间,但是viewStub不会。

再来看看view的gone属性,This view is invisible, and it doesn't take any space for layout purposes,那么设置了gone的view会被调用inflate方法吗?不会,因为他不占据空间,到现在为止,好像viewStub和gone的功能是类似的,看下面一段从ViewStub类中摘出来的一段代码

private void initialize(Context context) {
mContext
= context;
setVisibility(GONE);
setWillNotDraw(
true);
}

首先设置这个view的visible属性为gone,然后有设置了该类不能进行draw绘制。

ViewStub的原理是:ViewStub的属性设置为gone,并且不会被绘制,当设置了 setWillNotDraw(true)后,他的onDraw方法不会被调用,并且在他的onMeasure方法中,设置他的长度和宽度都为0,这样这个类就不会占用空间了,因为ViewStub是包含其他的布局文件,类似于include,ViewStub也是个view,自己本身能够被创建,但是他包含的布局文件是不会被加载的,即不会被inflate,所以也就不会消耗太多内存。如何保证ViewStub包含的布局文件不会被加载:

主要是通过设置 setWillNotDraw(true)方法。

这里引申一个网友的一篇文章:

一.引言:

想必大家以前也遇到過這個問題:出於項目的需要,我們有時需要新建一個直接或者間接繼承View的類,以便複寫View提供的onDraw()方法,但有時我們反而得不到我們想要的結果,今天就說一下onDraw()方法不被執行的解決方法。你可能也在onDraw()方法裡面設置了斷點或log,卻發現程序並沒有執行onDraw()方法,那麼你需要在你直接或者間接繼承View的類的構造函數中加入下面的語句:

setWillNotDraw(
false);

二.解釋:

那麼加這條語句的作用是什麼?先看API:

If
this view doesn't do any drawing on its own, set this flag to allow further optimizations. By default, this flag is not set on View, but could be set on some View subclasses such as ViewGroup. Typically, if you override onDraw(Canvas) you should clear this flag.

本人外語基礎不是很好,簡要翻譯一下,如果翻譯的不好,不要扔磚啊,重複一句我的語言:要想像,沒有了想像,世界會是什麼樣。嘿嘿:

如果在當前的view上面不做任何的繪製操作,需要設置這個標記以便將來的更好的需要,默認的,這個標記在View裡是不設定的。但是像View的一些子類如ViewGroup是可以設定的,典型的,你如果複寫了onDraw(Canvas)方法,你需要清除此標記。

那麼正好,我們所實現的就是View的子類:LinearLayout,當然你也可以繼承其他的子類如:

AbsoluteLayout,AdapterView
<T extends Adapter>,FrameLayout,LinearLayout,RelativeLayout,SlidingDrawer,子類就不說了,你可以自己去查文檔。

這條語句要放在繼承類的構造函數中,如:

public class BackgroundLayout extends LinearLayout {

public BackgroundLayout(Context context, int position) {

super(context);

// TODO Auto-generated constructor stub

setWillNotDraw(
false);

}

@Override

protected void onDraw(Canvas canvas) {

// TODO Auto-generated method stub

super.onDraw(canvas);

}

}

}

三,擴展看法:

eoeandroid上面Little關於這條語句的看法是:

设置view是否更改,如果开发者用自定义的view,重写ondraw()应该将调用此方法设置为false,这样程序会调用自定义的布局。

在此引用一下。

其實從這條語句的字面意思上可以看出:setWillNotDraw(
false);就是設置將不繪畫嗎?你重寫了onDraw()當然是要進行繪畫了,所以應將此語句參數置為false.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
0, 0);
}

当调用了ViewStub的inflate方法之后,ViewStub包含的布局文件就会被加载,inflate,ViewStub这个view对象是没有用的,他就起到一个包含子布局的作用,当子布局inflate之后,需要将他本身移除,将子布局对象填充进来,这样更节省内存空间,这里可以看下源码:

public View inflate() {
final ViewParent viewParent = getParent();

if (viewParent != null && viewParent instanceof ViewGroup) {
if (mLayoutResource != 0) {
final ViewGroup parent = (ViewGroup) viewParent;
final LayoutInflater factory = LayoutInflater.from(mContext);
final View view = factory.inflate(mLayoutResource, parent,
false);

if (mInflatedId != NO_ID) {
view.setId(mInflatedId);
}

final int index = parent.indexOfChild(this);
parent.removeViewInLayout(
this);

final ViewGroup.LayoutParams layoutParams = getLayoutParams();
if (layoutParams != null) {
parent.addView(view, index, layoutParams);
}
else {
parent.addView(view, index);
}

mInflatedViewRef
= new WeakReference<View>(view);

if (mInflateListener != null) {
mInflateListener.onInflate(
this, view);
}

return view;
}
else {
throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
}
}
else {
throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
}
}

  3. 解决topic图片在低清手机和高清手机上的适配问题,centercrop属性,动态该表itemview的高度,重新建立ListView与Adpater的连接

  centerCrop属性的作用是等比例的拉伸图片,使得这个图片的大小等于或者大于view的长,宽(如果该图片的大小小于view的长宽,那么这个图片就会等比例的拉伸到view的长宽居中显示,如果该图片的长宽大于该view的长宽,就会出现图片缩小居中显示的情况,(这就和该属性描述不一样了,至于为什么,我也不清楚)),然后居中显示。

  这么一种情况,有一个图片,作为ListView中的item的背景,该图片的大小为480px X 160px,htc g2的屏幕大小为320×480,该图片的宽度大于手机屏幕的宽度,M9的屏幕是640×960的,图片横向无法充满整个屏幕,怎么进行适配呢?

  解决方案是设置imageview的scaletype属性为centercrop,同时动态的改变该imageview的长宽,因为是等比例拉伸,所以imageview 的长宽也要满足该图片的长宽比例,这样才能等比例拉伸,否则图片拉伸后就会失真。设置imageview的width为fillparent,动态的取得该屏幕的长度然后按照相应比例获得view的hight。

  还有一个问题,当发生横竖屛切换的时候,ListView回去重新绘制itemView,如果在getView中计算长宽的话,那么每绘制一个view,都要计算一次,因为会复用以前的itemview,可以在onConfigrationChanged方法中重新设置setAdapter,这样就会重新创建itemview了,在ItemVIew的构造方法中设置一次hight,避免了每次调用getview,都要设置一遍的问题。

  4. 压缩文件的解压缩

  5. Gallery的使用

  6. ScrollView的使用

  7. 图片的平铺

  8. 异步下载图片的机制

  9. 设置图片的大小的方法

  10. 解析xml的方式,先dom解析,然后进行sars或者pull解析的优势

  11. HashSet的equals和hashCode的重写问题

  12. 一个错误,在一个LinearLayout中,横向放置三个 LinearLayout,分别设置他们的weight为0,1,0中间的 LinearLayout不放置任何东西,用来作为填充用,经过实验,这种做法不行,如果一个 LinearLayout容器中没有放置任何东西,他是不会拉伸的。他是根据他里面的内容来决定自身大小的。将中间的 LinearLayout改为View后就ok了。后来又研究了一下,发现使用 LinearLayout也是可以的,为什么呢?

  13. 有一个包含了三个linearLayout的布局文件 bar.xml,在一个activity的下方的工具条和上方的菜单上都使用了这个布局,这样就有几个问题,

    一是通过activity的findviewbyid方法不能获取自己想要的控件,因为activity中出现了相同id的控件

    二是怎么复用这个布局

  

posted on 2011-05-12 21:56  Android火鸟  阅读(6028)  评论(7编辑  收藏  举报