Предложение за подобряване на производителността на ListView

Използвам персонализиран списъчен изглед, за да покажа изображение и текст. По-долу е файлът с оформлението за моя елемент от списъчен изглед и кодът зад него. Ще обясня проблема си в долната част на публикацията.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="5dp"
    tools:context=".MainActivity" >

    <ImageView
        android:id="@+id/imgTitleImage"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:scaleType="fitXY" />

    <TextView
        android:id="@+id/tvNewsTitle"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/imgTitleImage"
        android:layout_alignStart="@+id/imgTitleImage"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:paddingLeft="10dp"
        android:paddingStart="10dp"
        android:paddingRight="10dp"
        android:paddingEnd="10dp"
        android:paddingTop="2dp"
        android:paddingBottom="2dp"
        android:gravity="top|start"
        android:textColor="#FFFFFF"         
        android:background="#80000000" />
</RelativeLayout>

По-долу е кодът на бекенда за зареждане на необходимата информация в списъчния изглед.

public View getView(final int position, View convertView, ViewGroup parent) 
    {
        SessionManagement sessionmanagement = new SessionManagement(context);
        ViewHolder holder = null;

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.news_item, null);
            holder = new ViewHolder();
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder)convertView.getTag();
        }

        convertView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Touch on view handle                              
                ObjNews objNews = objNewss[position];

                Intent intent = new Intent(activity, NewsViewActivity.class);       

                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                intent.putExtra("newsId", String.valueOf(objNews.newsId));
                intent.putExtra("type", String.valueOf(Config.NEWS_BRANCH));

                context.startActivity(intent);
            }

        });

        holder.imageView = (ImageView)convertView.findViewById(R.id.imgTitleImage);

        //calculate the screen size and image ratio
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);

        int width = size.x;
        float screenRatio = width / 320f;

        holder.imageView.getLayoutParams().height = (int)(75f * screenRatio);
        holder.imageView.getLayoutParams().width = (int)(320f * screenRatio);

        Bitmap titleImage = Global.GetBitmapFromURL("http://www.domain.com/" + objNewss[position].titleImage);

        if(titleImage != null)
        {
            holder.imageView.setImageBitmap(titleImage);
        }   
        else
        {
            holder.imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.news_title_default));    
        }

        //customizing view
        holder.textView = (TextView)convertView.findViewById(R.id.tvNewsTitle);
        holder.textView.setText(objNewss[position].title);                     

        return convertView;
    }

Тези парчета код работят перфектно, изображението и текстът се зареждат добре. Въпреки това, когато броят на артикулите се увеличи, времето за зареждане също се увеличи. Екранът ще бъде празен в очакване изгледът да се зареди. По-долу е полученото logcat.

12-21 03:54:20.827: D/OpenGLRenderer(1248): Активиране на режим на отстраняване на грешки 0

12-21 03:54:20.955: I/Choreographer(1248): Пропуснати 36 кадъра! Приложението може да върши твърде много работа върху основната си нишка.

12-21 03:54:24.991: D/dalvikvm(1248): GC_FOR_ALLOC освободи 467K, 14% свободно 4447K/5116K, пауза 8ms, общо 17ms

12-21 03:54:35.587: D/dalvikvm(1248): GC_FOR_ALLOC освободи 263K, 16% свободно 4416K/5220K, пауза 7ms, общо 9ms

12-21 03:54:35.591: I/dalvikvm-heap(1248): Увеличете купчината (случай на фрагмент) до 4,647MB за 148492-байтово разпределение

12-21 03:54:35.607: D/dalvikvm(1248): GC_FOR_ALLOC освободен ‹1K, 16% свободен 4560K/5368K, на пауза 14ms, общо 15ms

12-21 03:54:43.363: D/dalvikvm(1248): GC_FOR_ALLOC освободени 322K, 18% свободни 4415K/5368K, пауза 8ms, общо 8ms

12-21 03:54:44.611: D/dalvikvm(1248): GC_FOR_ALLOC освободени 281K, 18% свободни 4415K/5368K, пауза 8ms, общо 9ms

12-21 03:54:46.531: W/EGL_genymotion(1248): eglSurfaceAttrib не е внедрен

12-21 03:54:48.115: D/dalvikvm(1248): GC_FOR_ALLOC освободени 284K, 18% свободни 4420K/5368K, пауза 8ms, общо 10ms

12-21 03:54:49.983: D/dalvikvm(1248): GC_FOR_ALLOC освободени 323K, 18% свободни 4429K/5368K, пауза 6ms, общо 6ms

12-21 03:54:50.339: D/dalvikvm(1248): GC_FOR_ALLOC освободени 280K, 18% свободни 4439K/5368K, пауза 11ms, общо 11ms

12-21 03:54:50.551: I/Choreographer(1248): Пропуснати 1523 кадъра! Приложението може да върши твърде много работа върху основната си нишка.

12-21 03:54:51.263: D/dalvikvm(1248): GC_FOR_ALLOC освободени 288K, 17% свободни 4500K/5368K, пауза 8ms, общо 9ms

12-21 03:54:54.115: D/dalvikvm(1248): GC_FOR_ALLOC освободени 326K, 17% свободни 4497K/5368K, пауза 7ms, общо 9ms

12-21 03:54:54.531: D/dalvikvm(1248): GC_FOR_ALLOC освободени 281K, 17% свободни 4496K/5368K, пауза 10ms, общо 10ms

12-21 03:54:55.871: D/dalvikvm(1248): GC_FOR_ALLOC освободени 287K, 17% свободни 4506K/5368K, пауза 8ms, общо 9ms

12-21 03:54:56.591: D/dalvikvm(1248): GC_FOR_ALLOC освободени 324K, 17% свободни 4506K/5368K, пауза 7ms, общо 8ms

12-21 03:54:57.339: D/dalvikvm(1248): GC_FOR_ALLOC освободени 281K, 17% свободни 4506K/5368K, пауза 7ms, общо 8ms

Това може да се дължи на "Bitmap titleImage = Global.GetBitmapFromURL("http://www.domain.com/ " + objNewss[позиция].titleImage);" този ред код. Ако се коментира натоварването значително по-бързо.

Мога ли да знам дали някой експерт има по-добро предложение за мен? Още по-добре, ако може да се приложи асинхронно зареждане като groupon и т.н., където се зарежда и показва ред по ред, което няма да пречи на потребителското изживяване.

Много благодаря.


person TPG    schedule 21.12.2014    source източник


Отговори (2)


Изглежда, че Global.GetBitmapFromURL работи в основната нишка. Всяка мрежова заявка трябва да се извършва в отделна нишка, така че трябва да я преместите в AsyncTask или Loader, което ще реши проблема ви.

person Dara    schedule 21.12.2014

Не използвате структурата. Това е копие на класа EfficientAdapter, написано от екипа за разработка на Android.

По време на оценяването на convertView вие трябва да присвоявате своите holder стойности.

Като присвоите стойността след условията, тя ще се извиква всеки път.

WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();

Point size;

float ratio = -1;

//calculate the screen size and image ratio
void float getRatio()
{
    if(ratio == -1)
    {
        size = new Point();

        display.getSize(size);

        int width = size.x;

        ratio = width / 320f;
    }

    return ratio;
}

Bitmap titleImage;

Drawable news_title_default = context.getResources().getDrawable(R.drawable.news_title_default);

public View getView(final int position, View convertView, ViewGroup parent) 
{
    ViewHolder holder = null;

    if (convertView == null) {
        convertView = inflater.inflate(R.layout.news_item, null);
        holder = new ViewHolder();

        // assign the holder values
        holder.imageView = (ImageView)convertView.findViewById(R.id.imgTitleImage);
        holder.textView = (TextView)convertView.findViewById(R.id.tvNewsTitle);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder)convertView.getTag();
    }

    convertView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Touch on view handle                              
            ObjNews objNews = objNewss[position];

            Intent intent = new Intent(activity, NewsViewActivity.class);       

            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            intent.putExtra("newsId", String.valueOf(objNews.newsId));
            intent.putExtra("type", String.valueOf(Config.NEWS_BRANCH));

            context.startActivity(intent);
        }

    });

    holder.imageView.getLayoutParams().height = (int)(75f * getRatio());
    holder.imageView.getLayoutParams().width = (int)(320f * getRatio());

    titleImage = Global.GetBitmapFromURL("http://www.domain.com/" + objNewss[position].titleImage);

    if(titleImage != null)
    {
        holder.imageView.setImageBitmap(titleImage);
    }   
    else
    {
        holder.imageView.setImageDrawable(news_title_default);    
    }

    //customizing view

    holder.textView.setText(objNewss[position].title);                     

    return convertView;
}
person mrres1    schedule 21.12.2014