更新2011-08-29 如果我删除NodePickup中的图像,则拉扯会消失。
问题是 - 为什么?
----
我又回来尝试一些Android开发了。我有一个“旧的”HTC Hero手机,所以我启动了一个,做了一些更新,现在再次运行Eclipse和其他。
我在设备上运行了Android 2.1。
我做了一个非常简单的测试应用程序,除了显示一些活动等之外什么都不做。即使没有数据库连接,也没有从任何网络获取数据的应用程序非常慢。非常慢。
例如,我有一个带有一些自定义布局项的ListView。当只添加6-7个项目(这样我滚动)时,滚动时速度非常慢。此外,我有一些按钮可以更改活动,而且非常慢:
mButtonListenerUPP = new OnClickListener() {
@Override
public void onClick(View v)
{
Intent myIntent = new Intent(BaseActivity.this, ActivityMain.class);
BaseActivity.this.startActivity(myIntent);
}
};
我无法弄清楚为什么,所以我只是在这里发布代码并希望有人给我一些提示=)
THX!
适配器,NodeRowAdapter
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.view.*;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class NodeRowAdapter extends ArrayAdapter
{
private Activity context;
private ArrayList<Node> mList;
private LayoutInflater inflater;
NodeRowAdapter(Activity context, ArrayList<Node> objects)
{
super(context, R.layout.nodepickup, objects);
this.context=context;
mList = objects;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
class ViewHolder
{
TextView name;
TextView time;
TextView road;
Node node;
}
public Node getNode(int position)
{
if (mList != null && mList.size() > position)
return mList.get(position);
else
return null;
}
public View getView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
ViewHolder holder;
if (view == null)
{
view = inflater.inflate(R.layout.nodepickup, parent, false);
holder = new ViewHolder();
holder.name =(TextView)view.findViewById(R.id.name);
holder.time =(TextView)view.findViewById(R.id.time);
holder.road =(TextView)view.findViewById(R.id.road);
view.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
Node node = mList.get(position);
holder.name.setText(node.name);
holder.time.setText(node.time);
holder.road.setText(node.road);
return(view);
}
}
主要活动,ActivityMain
public class ActivityMain extends BaseActivity
{
private NodeRowAdapter _nodeRowAdapter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SICApplication._myContext = this;
SICApplication._myContext = this;
_nodeRowAdapter = new NodeRowAdapter(this, SICApplication.dataHolder_activityMain._nodes);
ListView listView1 = (ListView) findViewById(R.id.ListViewNodes);
listView1.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Node node = _nodeRowAdapter.getNode(position);
Log.v("MyApp", "Node=" + node.name);
}
});
listView1.setAdapter(_nodeRowAdapter);
}
/* Handles item selections */
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.add_item:
addNodeItem();
return true;
}
return false;
}
private void addNodeItem()
{
_nodeRowAdapter.add(new Node("Test", "asd asd ", "14:00", 1));
}
}
自定义列表项NodePickup
public class NodePickup extends LinearLayout
{
public NodePickup(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.nodepickup, this);
this.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setMessage("Ajabaja!")
.setCancelable(true)
.setPositiveButton("JA!", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.cancel();
}
});
builder.show();
}
});
}
}
最后,NodePickup XML布局
<LinearLayout
android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="64dip"
android:orientation="horizontal"
android:background="@drawable/stateful_background"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="@+id/ImageView01"
android:layout_width="40dip"
android:layout_height="40dip"
android:src="@drawable/arrow_up_green"
android:background="@android:color/transparent">
</ImageView>
<LinearLayout
android:id="@+id/LinearLayout02"
android:background="@android:color/transparent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:text="14:46 (15 min)"
android:id="@+id/time"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
</TextView>
<TextView
android:text="test"
android:id="@+id/road"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
</TextView>
<TextView
android:text="test test"
android:id="@+id/name"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
</TextView>
</LinearLayout>
</LinearLayout>
答案 0 :(得分:17)
更新2011-08-29如果我删除NodePickup中的图像,那么懒散就会消失。
该视图很难确定应如何呈现布局。您发布的xml没有多大帮助。如果删除ImageView,则LinearLayout02将占用父级的所有宽度。但是使用带有标准尺寸的imageView和右边的布局会使fill_parent混淆视图。再次请求imageView的大小“将边距向右推”(种类)。看看下面的建议
<强>提示1 强>
使用LinearLayout属性权重。同时制作imageView fill_parent和LinearLayout(宽度)并使用权重属性。 也可以使用TextViews进行垂直布局。最好的解决方案是将固定大小放在TextViews思想的高度上。 还要考虑将顶视图更改为RelativeLayout。使用标准尺寸,AlignParentLeft制作图像,并将LinearLayout02设置为RightOf imageView。你将大量放宽ViewGroup的onMeasure。
<强>提示2 强>
似乎当文本改变高度时,整个视图需要重新充气。一种常见的技术,以避免它使列表项固定在高度。因此列表视图可以重用循环视图而不重新填充。
<强>提示3 强>
为你的LinearLayout02提供64dp或Fill_Parent的固定高度,因为你没有任何剩余空间,但是布局不知道并且每次都尝试重新排列它,因为文本也是Wrap_content。
另外你说如果你删除了ImageView,一切都很快。如果上面没有任何效果你能试试吗?因为您知道imageView大小是固定的。
扩展imageView并覆盖requestLayout()方法。
public class MyImageView extends ImageView {
public PImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public PImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PImageView(Context context) {
super(context);
}
@Override
public void requestLayout() {
/*
* Do nothing here
*/
}
}
现在将MyImageView小部件包含在您的XML中。
<com.package_name.MyImageView
android:id="@+id/ImageView01"
android:layout_width="40dip"
android:layout_height="40dip"
android:src="@drawable/arrow_up_green"
android:background="@android:color/transparent">
</com.package_name.MyImageView >
答案 1 :(得分:15)
优化我的getView()方法以使用持有者并重用convertView,如果它不为null,我的listview仍然相当滞后。 然后,我试过了
listView.setScrollingCacheEnabled(false);
它立即解决了。
希望这有助于某人。
答案 2 :(得分:6)
我刚刚发现了这个,我想与你们分享。
我尝试了所有提供的解决方案但没有任何效果。导致问题的原因是我正在为我的一个TextView视图提供文本的长度,因为我正在使用
mTextView.SetText(theLongString)
在我的getView方法的适配器中。现在我收缩了我的String,listview非常顺利:)
答案 3 :(得分:1)
花了一段时间!我尝试了一切。禁用滚动缓存,viewHolder,cacheColorHint ......但没有任何效果!
经过几个小时的搜索,我找到了万恶之源!
在我的themes.xml中,我有一个缩放背景图片:
<item name="android:windowBackground">@drawable/window_bg</item>
去除beackground后,一切都是黄油光滑的。
我希望这有助于某人!
答案 4 :(得分:1)
要提高listview的性能,请使用两者之一或两者中的任何一个 - (简单实现)
如果您有适度长的列表,我推荐使用ViewHolder,对于大型列表(如音乐播放器),我建议使用ViewHolder和AsyncTask。平滑ListView滚动的关键是尽可能减少内存消耗。
要实现ViewHolder,很简单。只需在自定义适配器中创建一个静态类,它包含通过findViewById找到的所有视图。所以它应该是这样的 -
static class ViewHolder
{
TextView text;
TextView timestamp;
ImageView icon;
ProgressBar progress;
int position;
}
然后,下次你需要查找ViewById中的任何一个视图时,只需像这样引用ViewHolder -
ViewHolder holder = new ViewHolder();
holder.icon = (ImageView) yourView.findViewById(R.id.listitem_image);
holder.text = (TextView) yourView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) yourView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) yourView.findViewById(R.id.progress_spinner);
这是经过测试的代码,取自我的一个项目。但是,原始来源位于此处 - http://developer.android.com/training/improving-layouts/smooth-scrolling.html
使用ViewHolder,列表变得更加流畅。使用AsyncTask有点复杂,但如果您希望与ViewHolder一起实现AsyncTask以获得更流畅的滚动体验,请查看链接。祝你好运!
答案 5 :(得分:0)
将图像作为位图加载一次,然后在充气后以编程方式将其应用于ImageView。如果每个项目需要不同的图像,则应该像Android: How to optimize ListView with ImageView + 3 TextViews?
中所述异步创建位图。答案 6 :(得分:0)
尝试使用android:cacheColorHint="#00000000"
作为列表视图。为了提高滚动操作期间的绘图性能,Android框架重用了缓存颜色提示。
参考:developer.android.com文章。
答案 7 :(得分:0)
这可能会帮助一些人
如果列表项中有图像,则必须记住降低图像的质量。加载几Kb而不是几兆字节的速度更快。
这对我有帮助
public Bitmap MakeFileSmaller_ToBitmap(File f) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// The new size we want to scale to
final int REQUIRED_SIZE=200;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while(o.outWidth / scale / 2 >= REQUIRED_SIZE &&
o.outHeight / scale / 2 >= REQUIRED_SIZE) {
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
Log.d(TAG, "FILE NOT FOUND " );
}
Log.d(TAG, "OTHER EXCEPTION");
return null;
}
答案 8 :(得分:0)
之前我遇到了同样的问题,而我使用不同的布局,如LinearLayout,RelativeLayout,CardView作为同一列表视图项目中不同子项的父级。我通过更改RelativeLayout中的所有视图解决了这个问题。
使用RelativeLayout作为主要内容,它的子布局可能会提高加载每个项目的速度。所以滚动会很顺利。
<RelativeLayout
android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="64dip"
android:orientation="horizontal"
android:background="@drawable/stateful_background"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="40dip"
android:layout_height="40dip"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="@+id/relativeLayout">
<ImageView
android:id="@+id/ImageView01"
android:layout_width="40dip"
android:layout_height="40dip"
android:src="@drawable/arrow_up_green"
android:background="@android:color/transparent">
</ImageView>
</RelativeLayout>
<TextView
android:text="14:46 (15 min)"
android:id="@+id/time"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/relativeLayout"
android:layout_toEndOf="@+id/relativeLayout" />
<TextView
android:text="test"
android:id="@+id/road"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:layout_below="@+id/time"
android:layout_toRightOf="@+id/relativeLayout"
android:layout_toEndOf="@+id/relativeLayout" />
<TextView
android:text="test test"
android:id="@+id/name"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:layout_below="@+id/road"
android:layout_toRightOf="@+id/relativeLayout"
android:layout_toEndOf="@+id/relativeLayout"/></RelativeLayout>
答案 9 :(得分:0)
你可以使用 listview.setScrollingCacheEnabled(false)。当滚动listview应用程序保持区域然后抛出内存(OOM)异常。我的解决方案对我有效。