Android Gridview - 跳过的帧和垃圾收集错误

时间:2016-08-02 18:10:11

标签: android performance gridview garbage-collection

为了给出一些上下文,我的应用有两个标签。其中一个选项卡显示GridView中游戏Pokemon Go中所有151个口袋妖怪的名称和图像。最大的图像是50kb。有时我的应用程序崩溃,日志显示一堆GC消息:

I/art: Waiting for a blocking GC Alloc
W/art: Suspending all threads took: 8.472ms
I/art: Clamp target GC heap from 145MB to 129MB
I/art: Alloc concurrent mark sweep GC freed 0(0B) AllocSpace objects, 0(0B) LOS objects, 0% free, 129MB/129MB, paused 281us total 9.184ms
I/art: WaitForGcToComplete blocked for 37.353ms for cause Alloc

当应用程序没有崩溃时(我不明白为什么它有时会因GC而崩溃)我得到了这个:

I/Choreographer: Skipped 53 frames!  The application may be doing too much work on its main thread.

我可以看到gridView是一个触摸延迟。我已经研究并对我的代码进行了更改,以使我的gridview更有效,但它仍然有点滞后。我想知道它是否是我存储图像的方式。我将发布我的主要活动,GridView适配器和我的Pokedex类,它包含一个包含图像和字符串资源的pokemon对象列表。如果您需要更多信息,请在评论中告诉我,提前谢谢。

public class GridAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater  mInflater;

public GridAdapter(Context c) {
    mContext = c;
    mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public int getCount() {
    return Pokedex.getNumberOfPokemon();
}

public Object getItem(int position) {
    return null;
}

public long getItemId(int position) {
    return 0;
}

// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    Pokemon current = Pokedex.getPokemon(position);
    if (convertView == null) {
        // if it's not recycled, initialize some attributes
        convertView = mInflater.inflate(R.layout.grid_item, parent, false);
        holder = new ViewHolder();
        holder.pokemonImage = (ImageView) convertView.findViewById(R.id.pokemon_image);
        holder.pokemonName = (TextView) convertView.findViewById(R.id.pokemon_name);
        convertView.setTag(holder);

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

    holder.pokemonImage.setImageResource(current.getImageResource());
    holder.pokemonName.setText(current.getNameResource());
    return convertView;
}

static class ViewHolder {
    ImageView pokemonImage;
    TextView pokemonName;
}
}

pokedex类:

public class Pokedex {
private final static ArrayList<Pokemon> list = new ArrayList<Pokemon>();

public static int getNumberOfPokemon(){
    return list.size();
}

public static Pokemon getPokemon(int position){
    return list.get(position);
}

static{
    list.add(new Pokemon(R.string.Bulbasaur, 1, R.drawable.bulbasaur));
    list.add(new Pokemon(R.string.Ivysaur, 2, R.drawable.ivysaur));
    list.add(new Pokemon(R.string.Venusaur, 3, R.drawable.venusaur));
    list.add(new Pokemon(R.string.Charmander, 4, R.drawable.charmander));
    list.add(new Pokemon(R.string.Charmeleon, 5, R.drawable.charmeleon));
    list.add(new Pokemon(R.string.Charizard, 6, R.drawable.charizard));
    list.add(new Pokemon(R.string.Squirtle, 7, R.drawable.squirtle));
    list.add(new Pokemon(R.string.Wartortle, 8, R.drawable.wartortle));
    list.add(new Pokemon(R.string.Blastoise, 9, R.drawable.blastoise));
    list.add(new Pokemon(R.string.Caterpie, 10, R.drawable.caterpie));
    list.add(new Pokemon(R.string.Metapod, 11, R.drawable.metapod));
    list.add(new Pokemon(R.string.Butterfree, 12, R.drawable.butterfree));
    list.add(new Pokemon(R.string.Weedle, 13, R.drawable.weedle));
    list.add(new Pokemon(R.string.Kakuna, 14, R.drawable.kakuna));
    list.add(new Pokemon(R.string.Beedrill, 15, R.drawable.beedrill));
    list.add(new Pokemon(R.string.Pidgey, 16, R.drawable.pidgey));
    list.add(new Pokemon(R.string.Pidgeotto, 17, R.drawable.pidgeotto));
    list.add(new Pokemon(R.string.Pidgeot, 18, R.drawable.pidgeot));
    list.add(new Pokemon(R.string.Rattata, 19, R.drawable.rattata));
    list.add(new Pokemon(R.string.Raticate, 20, R.drawable.raticate));
    list.add(new Pokemon(R.string.Spearow, 21, R.drawable.spearow));
    list.add(new Pokemon(R.string.Fearow, 22, R.drawable.fearow));
    list.add(new Pokemon(R.string.Ekans, 23, R.drawable.ekans));
    list.add(new Pokemon(R.string.Arbok, 24, R.drawable.arbok));
    list.add(new Pokemon(R.string.Pikachu, 25, R.drawable.pikachu));
    list.add(new Pokemon(R.string.Raichu, 26, R.drawable.raichu));
    list.add(new Pokemon(R.string.Sandshrew, 27, R.drawable.sandshrew));
    list.add(new Pokemon(R.string.Sandslash, 28, R.drawable.sandslash));
    list.add(new Pokemon(R.string.NidoranF, 29, R.drawable.nidoranf));
    list.add(new Pokemon(R.string.Nidorina, 30, R.drawable.nidorina));
    list.add(new Pokemon(R.string.Nidoqueen, 31, R.drawable.nidoqueen));
    list.add(new Pokemon(R.string.NidoranM, 32, R.drawable.nidoranm));
    list.add(new Pokemon(R.string.Nidorino, 33, R.drawable.nidorino));
    list.add(new Pokemon(R.string.Nidoking, 34, R.drawable.nidoking));
    list.add(new Pokemon(R.string.Clefairy, 35, R.drawable.clefairy));
    list.add(new Pokemon(R.string.Clefable, 36, R.drawable.clefable));
    list.add(new Pokemon(R.string.Vulpix, 37, R.drawable.vulpix));
    list.add(new Pokemon(R.string.Ninetales, 38, R.drawable.ninetales));
    list.add(new Pokemon(R.string.Jigglypuff, 39, R.drawable.jigglypuff));
    list.add(new Pokemon(R.string.Wigglytuff, 40, R.drawable.wigglytuff));
    list.add(new Pokemon(R.string.Zubat, 41, R.drawable.zubat));
    list.add(new Pokemon(R.string.Golbat, 42, R.drawable.golbat));
    list.add(new Pokemon(R.string.Oddish, 43, R.drawable.oddish));
    list.add(new Pokemon(R.string.Gloom, 44, R.drawable.gloom));
    list.add(new Pokemon(R.string.Vileplume, 45, R.drawable.vileplume));
    list.add(new Pokemon(R.string.Paras, 46, R.drawable.paras));
    list.add(new Pokemon(R.string.Parasect, 47, R.drawable.parasect));
    list.add(new Pokemon(R.string.Venonat, 48, R.drawable.venonat));
    list.add(new Pokemon(R.string.Venomoth, 49, R.drawable.venomoth));
    list.add(new Pokemon(R.string.Diglett, 50, R.drawable.diglett));
    list.add(new Pokemon(R.string.Dugtrio, 51, R.drawable.dugtrio));
    list.add(new Pokemon(R.string.Meowth, 52, R.drawable.meowth));
    list.add(new Pokemon(R.string.Persian, 53, R.drawable.persian));
    list.add(new Pokemon(R.string.Psyduck, 54, R.drawable.psyduck));
    list.add(new Pokemon(R.string.Golduck, 55, R.drawable.golduck));
    list.add(new Pokemon(R.string.Mankey, 56, R.drawable.mankey));
    list.add(new Pokemon(R.string.Primeape, 57, R.drawable.primeape));
    list.add(new Pokemon(R.string.Growlithe, 58, R.drawable.growlithe));
    list.add(new Pokemon(R.string.Arcanine, 59, R.drawable.arcanine));
    list.add(new Pokemon(R.string.Poliwag, 60, R.drawable.poliwag));
    list.add(new Pokemon(R.string.Poliwhirl, 61, R.drawable.poliwhirl));
    list.add(new Pokemon(R.string.Poliwrath, 62, R.drawable.poliwrath));
    list.add(new Pokemon(R.string.Abra, 63, R.drawable.abra));
    list.add(new Pokemon(R.string.Kadabra, 64, R.drawable.kadabra));
    list.add(new Pokemon(R.string.Alakazam, 65, R.drawable.alakazam));
    list.add(new Pokemon(R.string.Machop, 66, R.drawable.machop));
    list.add(new Pokemon(R.string.Machoke, 67, R.drawable.machoke));
    list.add(new Pokemon(R.string.Machamp, 68, R.drawable.machamp));
    list.add(new Pokemon(R.string.Bellsprout, 69, R.drawable.bellsprout));
    list.add(new Pokemon(R.string.Weepinbell, 70, R.drawable.weepinbell));
    list.add(new Pokemon(R.string.Victreebel, 71, R.drawable.victreebel));
    list.add(new Pokemon(R.string.Tentacool, 72, R.drawable.tentacool));
    list.add(new Pokemon(R.string.Tentacruel, 73, R.drawable.tentacruel));
    list.add(new Pokemon(R.string.Geodude, 74, R.drawable.geodude));
    list.add(new Pokemon(R.string.Graveler, 75, R.drawable.graveler));
    list.add(new Pokemon(R.string.Golem, 76, R.drawable.golem));
    list.add(new Pokemon(R.string.Ponyta, 77, R.drawable.ponyta));
    list.add(new Pokemon(R.string.Rapidash, 78, R.drawable.rapidash));
    list.add(new Pokemon(R.string.Slowpoke, 79, R.drawable.slowpoke));
    list.add(new Pokemon(R.string.Slowbro, 80, R.drawable.slowbro));
    list.add(new Pokemon(R.string.Magnemite, 81, R.drawable.magnemite));
    list.add(new Pokemon(R.string.Magneton, 82, R.drawable.magneton));
    list.add(new Pokemon(R.string.Farfetchd, 83, R.drawable.farfetchd));
    list.add(new Pokemon(R.string.Doduo, 84, R.drawable.doduo));
    list.add(new Pokemon(R.string.Dodrio, 85, R.drawable.dodrio));
    list.add(new Pokemon(R.string.Seel, 86, R.drawable.seel));
    list.add(new Pokemon(R.string.Dewgong, 87, R.drawable.dewgong));
    list.add(new Pokemon(R.string.Grimer, 88, R.drawable.grimer));
    list.add(new Pokemon(R.string.Muk, 89, R.drawable.muk));
    list.add(new Pokemon(R.string.Shellder, 90, R.drawable.shellder));
    list.add(new Pokemon(R.string.Cloyster, 91, R.drawable.cloyster));
    list.add(new Pokemon(R.string.Gastly, 92, R.drawable.gastly));
    list.add(new Pokemon(R.string.Haunter, 93, R.drawable.haunter));
    list.add(new Pokemon(R.string.Gengar, 94, R.drawable.gengar));
    list.add(new Pokemon(R.string.Onix, 95, R.drawable.onix));
    list.add(new Pokemon(R.string.Drowzee, 96, R.drawable.drowzee));
    list.add(new Pokemon(R.string.Hypno, 97, R.drawable.hypno));
    list.add(new Pokemon(R.string.Krabby, 98, R.drawable.krabby));
    list.add(new Pokemon(R.string.Kingler, 99, R.drawable.kingler));
    list.add(new Pokemon(R.string.Voltorb, 100, R.drawable.voltorb));
    list.add(new Pokemon(R.string.Electrode, 101, R.drawable.electrode));
    list.add(new Pokemon(R.string.Exeggcute, 102, R.drawable.exeggcute));
    list.add(new Pokemon(R.string.Exeggutor, 103, R.drawable.exeggutor));
    list.add(new Pokemon(R.string.Cubone, 104, R.drawable.cubone));
    list.add(new Pokemon(R.string.Marowak, 105, R.drawable.marowak));
    list.add(new Pokemon(R.string.Hitmonlee, 106, R.drawable.hitmonlee));
    list.add(new Pokemon(R.string.Hitmonchan, 107, R.drawable.hitmonchan));
    list.add(new Pokemon(R.string.Lickitung, 108, R.drawable.lickitung));
    list.add(new Pokemon(R.string.Koffing, 109, R.drawable.koffing));
    list.add(new Pokemon(R.string.Weezing, 110, R.drawable.weezing));
    list.add(new Pokemon(R.string.Rhyhorn, 111, R.drawable.rhyhorn));
    list.add(new Pokemon(R.string.Rhydon, 112, R.drawable.rhydon));
    list.add(new Pokemon(R.string.Chansey, 113, R.drawable.chansey));
    list.add(new Pokemon(R.string.Tangela, 114, R.drawable.tangela));
    list.add(new Pokemon(R.string.Kangaskhan, 115, R.drawable.kangaskhan));
    list.add(new Pokemon(R.string.Horsea, 116, R.drawable.horsea));
    list.add(new Pokemon(R.string.Seadra, 117, R.drawable.seadra));
    list.add(new Pokemon(R.string.Goldeen, 118, R.drawable.goldeen));
    list.add(new Pokemon(R.string.Seaking, 119, R.drawable.seaking));
    list.add(new Pokemon(R.string.Staryu, 120, R.drawable.staryu));
    list.add(new Pokemon(R.string.Starmie, 121, R.drawable.starmie));
    list.add(new Pokemon(R.string.MrMime, 122, R.drawable.mrmime));
    list.add(new Pokemon(R.string.Scyther, 123, R.drawable.scyther));
    list.add(new Pokemon(R.string.Jynx, 124, R.drawable.jynx));
    list.add(new Pokemon(R.string.Electabuzz, 125, R.drawable.electabuzz));
    list.add(new Pokemon(R.string.Magmar, 126, R.drawable.magmar));
    list.add(new Pokemon(R.string.Pinsir, 127, R.drawable.pinsir));
    list.add(new Pokemon(R.string.Tauros, 128, R.drawable.tauros));
    list.add(new Pokemon(R.string.Magikarp, 129, R.drawable.magikarp));
    list.add(new Pokemon(R.string.Gyarados, 130, R.drawable.gyarados));
    list.add(new Pokemon(R.string.Lapras, 131, R.drawable.lapras));
    list.add(new Pokemon(R.string.Ditto, 132, R.drawable.ditto));
    list.add(new Pokemon(R.string.Eevee, 133, R.drawable.eevee));
    list.add(new Pokemon(R.string.Vaporeon, 134, R.drawable.vaporeon));
    list.add(new Pokemon(R.string.Jolteon, 135, R.drawable.jolteon));
    list.add(new Pokemon(R.string.Flareon, 136, R.drawable.flareon));
    list.add(new Pokemon(R.string.Porygon, 137, R.drawable.porygon));
    list.add(new Pokemon(R.string.Omanyte, 138, R.drawable.omanyte));
    list.add(new Pokemon(R.string.Omastar, 139, R.drawable.omastar));
    list.add(new Pokemon(R.string.Kabuto, 140, R.drawable.kabuto));
    list.add(new Pokemon(R.string.Kabutops, 141, R.drawable.kabutops));
    list.add(new Pokemon(R.string.Aerodactyl, 142, R.drawable.aerodactyl));
    list.add(new Pokemon(R.string.Snorlax, 143, R.drawable.snorlax));
    list.add(new Pokemon(R.string.Articuno, 144, R.drawable.articuno));
    list.add(new Pokemon(R.string.Zapdos, 145, R.drawable.zapdos));
    list.add(new Pokemon(R.string.Moltres, 146, R.drawable.moltres));
    list.add(new Pokemon(R.string.Dratini, 147, R.drawable.dratini));
    list.add(new Pokemon(R.string.Dragonair, 148, R.drawable.dragonair));
    list.add(new Pokemon(R.string.Dragonite, 149, R.drawable.dragonite));
    list.add(new Pokemon(R.string.Mewtwo, 150, R.drawable.mewtwo));
    list.add(new Pokemon(R.string.Mew, 151, R.drawable.mew));
}
}

MainActivity:

公共类MainActivity扩展了AppCompatActivity {

/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a
 * {@link FragmentPagerAdapter} derivative, which will keep every
 * loaded fragment in memory. If this becomes too memory intensive, it
 * may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
private SectionsPagerAdapter mSectionsPagerAdapter;

/**
 * The {@link ViewPager} that will host the section contents.
 */
private ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(mViewPager);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    public PlaceholderFragment() {
    }

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = null;

        switch(getArguments().getInt(ARG_SECTION_NUMBER)){
            case 1: {
                rootView = inflater.inflate(R.layout.fragment_main, container, false);
                break;
            }

            case 2: {
                rootView = inflater.inflate(R.layout.fragment_grid, container, false);

                GridView gridView = (GridView) rootView.findViewById(R.id.gridview);
                gridView.setAdapter(new GridAdapter(getActivity()));

                break;
            }
        }

        return rootView;
    }
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the sections/tabs/pages.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a PlaceholderFragment (defined as a static inner class below).
        return PlaceholderFragment.newInstance(position + 1);
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return "Main Tab";
            case 1:
                return "Pokedex Gridview";
        }
        return null;
    }
}

}

1 个答案:

答案 0 :(得分:0)

问题是您正在使用setImageResource方法,如在UI线程中运行的文档中所述,因此资源加载是同步的:

  

这会在UI线程上进行Bitmap读取和解码,这会导致延迟打嗝。如果这是一个问题,请考虑使用setImageDrawable(android.graphics.drawable.Drawable)或setImageBitmap(android.graphics.Bitmap)和BitmapFactory。

如上所述,你应该使用setImageDrawable方法(我认为它是异步加载drawable)。以下是在适配器的“getView”方法中获取可绘制对象的方法:getContext().getResources().getDrawable(R.drawable.my_drawable)。 请记住,在Android中,用户界面在主线程中呈现(因此其他名称为“UI线程”),因此您需要在那里执行较少的工作(Android以60 FPS运行渲染)。因为你在UI线程中做了太多的工作(加载资源),系统无法维持60 FPS,所以跳过很多帧。