【问题标题】:setImageBitmap() lags UIsetImageBitmap() 滞后于 UI
【发布时间】:2014-09-23 16:07:00
【问题描述】:

当我在任何 imageView 上调用 setImageBitmap() 时,它会滞后于 UI。我正在使用 listView 所以我必须在滚动时设置一个 imageView。请不要建议使用 Picasso 或其他图片下载助手,因为该问题与下载问题无关,并且对使用此类库没有帮助。

编辑:
适配器:

public class GönderiItemAdapter extends BaseAdapter{
    private final Activity mActivity;
    private final Vector<String> mVeri;
    private boolean mProfil = false;
    private boolean mKullanıcı;
    private boolean mArama = false;
    private Profil mProfilBilgi;
    private String mAramaString;



public GönderiItemAdapter( Activity pActivity, String[] pVeri, boolean pKullanıcı, Profil pProfililgi ){

    this(pActivity, pVeri);

    mProfil      = true;
    mKullanıcı   = pKullanıcı;
    mProfilBilgi = pProfililgi;

}

public GönderiItemAdapter( Activity pActivity, final String[] pVeri, String pAramaString ){

    this(pActivity, pVeri);

    mAramaString = pAramaString;
    mArama = true;
}

public GönderiItemAdapter( Activity pActivity, final String[] pVeri){

    if( Ayarlar.sGönderiler == null )
        Ayarlar.yükleGönderiler( pActivity );

    mActivity   = pActivity;

    mVeri = new Vector<String>();

    for( int i = 0; i < pVeri.length; ++i )
        mVeri.add( pVeri[ i ] );

    mProfil     = false;

}

public void ekleÜst( String[] pVeri ){

    for( int i = pVeri.length - 1; i >= 0; --i ){

        Gönderi gönderi = Ayarlar.alGönderi( pVeri[ i ], mActivity, false);

        if( !gönderi.mGönderenId.equals( "-1" ) )
            mVeri.add( 0 , pVeri[ i ] );

    }       
}

public void ekleAlt( String[] pVeri, final TextView pMetin ){

    for( int i = 0; i < pVeri.length; ++i ){

        Gönderi gönderi = Ayarlar.alGönderi( pVeri[ i ], mActivity, false);             

        if( gönderi.mGönderenId.equals( "-1" ) )
            mActivity.runOnUiThread( new Runnable() {

                @Override
                public void run() {
                    pMetin.setText( R.string.dahayok );
                }
            } );

        else
            mVeri.add( pVeri[ i ] );
    }

}

public void al( ){
    GenelEşzamansızİşlem giş = new GenelEşzamansızİşlem();
    giş.arkaplanİşlem = new Thread( new Runnable() {

        @Override
        public void run() {

            for( int i = 0; i < mVeri.size(); ++i )
                Ayarlar.alGönderi( mVeri.get( i ), mActivity, false);

        }
    } );
    if( Araçlar.mobilVeri(mActivity) )
        giş.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);

    else
        giş.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}

static public void al2( final String[] pVeri, final Activity pActivity ){
    GenelEşzamansızİşlem giş = new GenelEşzamansızİşlem();
    giş.arkaplanİşlem = new Thread( new Runnable() {

        @Override
        public void run() {     
            if( Ayarlar.sGönderiler == null )
                Ayarlar.yükleGönderiler(pActivity);

            Vector<String> idVector = new Vector<String>();

            for( int i = 0; i < pVeri.length; ++i )
                if( !Ayarlar.sGönderiler.containsKey( pVeri[i] ) )
                    idVector.add( pVeri[i] );

            String[] idArray = new String[ idVector.size() ];

            for( int i = 0; i < idArray.length; ++i )
                idArray[ i ] = idVector.get( i );

            if( idArray.length > 0 )
                Ayarlar.alTopluGönderi(idArray, pActivity);

        }
    } );

    try{
        giş.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR).get();
    }catch( Exception e ){
        e.printStackTrace();
    }
}



public void güncelle( ){

    for( int i = 0; i < mVeri.size(); ++i ){
        Ayarlar.alGönderi( mVeri.get( i ), mActivity, false).güncelle( mActivity );
    }

}

@Override
public int getCount(){

    if( mProfil )
        return mVeri.size() + 1;

    return mVeri.size();
}

@Override
public int getViewTypeCount(){
    return 2;
}

@Override
public Object getItem(int arg0) {
    return null;
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public int getItemViewType(int position){

    if( mProfil && position == 0 )
        return 1;
    else
        return 0;
}

@Override
public boolean areAllItemsEnabled(){
    return false;
}

@Override
public boolean isEnabled( int position ){
    return false;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub

    LayoutInflater inflater = (LayoutInflater) mActivity
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if( mProfil && position == 0 )
    {

        View v = inflater.inflate( R.layout.header_profil, null);


        final Button sağ        = (Button) v.findViewById( R.id.sag  );
        View   line1            =          v.findViewById( R.id.line1);
        final Button orta       = (Button) v.findViewById( R.id.orta );
        View   line2            =          v.findViewById( R.id.line2);
        final Button sol        = (Button) v.findViewById( R.id.sol  );

        if( mKullanıcı ){

            sağ.setVisibility( View.VISIBLE );

            sağ.setOnClickListener( new OnClickListener() {

                @Override
                public void onClick(View v) {
                    ( ( ExplorerActivity )mActivity ).yeniGönderi();
                }
            } );

            sağ.setText( R.string.yeniGonderi );

        } 

        else{

            sağ.setVisibility( View.GONE );
            line2.setVisibility( View.GONE );

            if( !Ayarlar.sFavoriler.contains( mProfilBilgi.mID ) )
                sol.setText( R.string.favoriEkle );
            else
                sol.setText( R.string.favoriCikar );

            sol.setVisibility( View.VISIBLE );

            sol.setOnClickListener( new OnClickListener() {

                @Override
                public void onClick(View v) {
                    ( ( ExplorerActivity )mActivity ).favori( mProfilBilgi.mID );

                    if( !Ayarlar.sFavoriler.contains( mProfilBilgi.mID ) )
                        sol.setText( R.string.favoriEkle );
                    else
                        sol.setText( R.string.favoriCikar );
                }
            } );

        }

        v.findViewById( R.id.profil ).setOnClickListener( new OnClickListener() {

            @Override
            public void onClick(View v) {
                ( ( ExplorerActivity )mActivity ).gösterProfil( mProfilBilgi );
            }
        } );

        return v;   
    }   

    else{

        if( mProfil )
            position -= 1;

        View v;
        Gönderi g;

        if( convertView == null ){

            v = inflater.inflate( R.layout.gonderi_liste_nesnesi, null);

            g = new Gönderi();
            g.mAnaDüzen         = (LinearLayout) v;
            g.mProfilFotoğrafı  = (CircularImageView) v.findViewById( R.id.profil_photo );
            g.mGönderenAdı      = (TextView) v.findViewById( R.id.gonderen_adi );
            g.mGönderiZamanı    = (TextView) v.findViewById( R.id.gonderi_tarihi );
            g.mDönem            = (TextView) v.findViewById( R.id.gonderen_donemi );
            g.mGönderi          = (TextView) v.findViewById( R.id.gonderi );
            g.mBeğen            = (TextView) v.findViewById( R.id.begen );
            g.mBeğeniText       = (TextView) v.findViewById( R.id.begeniSayi );

            v.setTag( g );

        }
        else{
            g = (Gönderi) convertView.getTag();
            v = convertView;
        }

        final Gönderi gönderi = Ayarlar.alGönderi( mVeri.get( position ), mActivity, false);

        g.mGönderenAdıString = gönderi.mGönderenAdıString;
        g.mDüzenliTarih = gönderi.mDüzenliTarih;
        g.mDönemString = gönderi.mDönemString;
        g.mGönderiHamMetin = gönderi.mGönderiHamMetin;
        g.mBeğeniTextString = gönderi.mBeğeniTextString;

        g.mBeğeni       = gönderi.mBeğeni;
        g.mBeğenildi    = gönderi.mBeğenildi;
        g.mBeğeniVerisi = gönderi.mBeğeniVerisi;
        g.mGönderenId   = gönderi.mGönderenId;
        g.mBeğeniSayısı = gönderi.mBeğeniSayısı;
        g.mGönderiId    = gönderi.mGönderiId;

        g.ayarla( mArama, mAramaString, mActivity);


        if( !mArama ){

            g.beğeniİşlemler( mActivity );

            if( g.mBeğenildi ){
                g.mBeğen.setOnClickListener( g.mBeğenmeİşlem );

                g.mBeğen.setText( R.string.hoslanma );
            }

            else
                g.mBeğen.setOnClickListener( g.mBeğenİşlem );

            final Gönderi foo = g;

            g.mBeğeniText.setOnClickListener( new OnClickListener() {

                @Override
                public void onClick(View v) {
                    final Dialog dialog = new Dialog( mActivity );

                    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);

                    dialog.setContentView(R.layout.dialog_begeni);

                    ListView liste = (ListView) dialog.findViewById( R.id.liste );

                    Vector<Profil> profiller = new Vector<Profil>();

                    for( int i = 0; i < foo.mBeğeni.size(); ++i ){

                        Profil p = Ayarlar.alProfil( foo.mBeğeni.get( i ).mGönderenID , mActivity);

                        Log.w( "id" , p.mID);

                        if( p != null && !p.mID.equals( Ayarlar.sMevcutId ) )
                            profiller.add( p );

                    }

                    KartAdapter adapter = new KartAdapter(mActivity, profiller, mActivity, dialog);

                    liste.setAdapter( adapter );

                    if( profiller.size() != 0 )
                        dialog.show();
                }
            } );


            g.mProfilFotoğrafı.setOnClickListener( new OnClickListener() {

                @Override
                public void onClick(View arg0) {
                    ((ExplorerActivity) mActivity).açProfil( gönderi.mGönderenId );
                }
            });

            g.mGönderenAdı.setOnClickListener( new OnClickListener() {

                @Override
                public void onClick(View arg0) {
                    ((ExplorerActivity) mActivity).açProfil( gönderi.mGönderenId );
                }
            });
        }
        else{
            g.mAnaDüzen.setOnClickListener( new OnClickListener() {

                @Override
                public void onClick(View arg0) {
                    ((ExplorerActivity) mActivity).açGönderi( gönderi.mGönderiId );
                }
            });
        }

        return v;
    }   
}

}

【问题讨论】:

  • 这很可能是垃圾收集器启动了,因为图像占用了它想要回收的内存。如果您不提供有关位图性质的任何信息(大小、来源、每个列表项是否不同...),则无法回答您的问题。
  • 它们是从服务器加载的,大小不同,每个项目也不同,但我是否从资源中设置可绘制并不重要
  • 由于您使用的是 ListView,我假设您在其中有某种缩略图。也许您正在加载一个大位图(不是样本大小)以便将其放置在那里。但是如果没有用于执行此操作的代码,我无法给出任何建议。您能否发布代码如何获取位图以及如何将其传递给 ImageView?如果你发布你的 ListView 适配器也会很有帮助。
  • 如果你真的想要,我可以发布适配器,但它真的很复杂,并且可以与其他类一起使用,我正在使用 Picasso 加载位图。当我看到它以这种方式滞后时,我尝试使用毕加索将图像加载到位图中,然后将位图设置为 imageview。但是每当我调用 ImageView.setImageBitmap() 或 setImageDrawable 时它都会滞后
  • 如果 gc 在没有 setImageBitmap 的情况下启动,那么您遇到的问题不仅仅是图像,使用 Traceview 可能是首先要解决的问题。如果 Android 想要释放一些内存,那么 gc 就会启动,如果应用程序分配了很多内存,这种情况会更频繁地发生,例如通过向 ListView 添加许多或大图像,但当然可能有无数不同的原因。无论如何,您还需要查看您的应用程序的内存使用情况,我会使用 MAT (eclipse.org/mat)。

标签: android imageview android-imageview


【解决方案1】:

你可以使用ViewHolder Design Pattern:

http://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder

使用图像占位符以防止您的列表图像混乱,并在下载完成后用您的图像替换图像占位符(如果它正在显示或

您可以使用新的 android 小部件:

https://developer.android.com/preview/material/ui-widgets.html#recyclerview

【讨论】:

  • 我正在使用一种视图支架设计模式,但我仍然有问题
  • 你能发布你的适配器吗!
【解决方案2】:

我已经解决了减少 gc 调用和组织适配器的问题。但真正的问题是文件输出。我减少了对文件输出函数的调用,它解决了我的问题。我将所有输出的文件放在 onPause 方法中。应用暂停时会有些延迟,但这是一种更好的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-21
    • 1970-01-01
    • 2016-07-19
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多