2016-08-02 50 views
0

爲了給出一點上下文,我的應用程序有2個選項卡。其中一個選項卡顯示來自Pokemon Go遊戲的所有151 pokemon在GridView中的名稱和圖像。最大的圖像是50kb。有時我的應用程序崩潰和日誌顯示一串GC消息:Android Gridview - 跳過的幀和垃圾收集錯誤

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是一個觸摸laggy。我研究並修改了我的代碼,以使我的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; 
} 
} 

的圖鑑類:

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; 
    } 
} 

}

回答

0

的問題是,你是USI納克的setImageResource方法,該方法如在該文檔指出在UI線程中運行,所以資源負載是同步的:

這確實位圖讀取和解碼UI線程,這可能導致延遲打嗝上。如果這是一個問題,請考慮使用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,因此跳過了很多幀。

+0

謝謝,但是getDrawable現在已被棄用,所以我使用holder.pokemonImage.setImageDrawable(ResourcesCompat.getDrawable(mContext.getResources(),current.getImageResource(),null));取而代之的是,但Gridview的滾動仍然不是非常流暢。也許我期待太多?它工作正常,gridview加載下一行時只有最小的延遲,當然如果我快速滾動它仍然會跳過幀。 – Vindictive

+0

哦,我看到了,這裏的問題是,我們每次調用「getView」方法時都會解碼位圖,所以我認爲爲了提高性能,實現緩存管理器非常重要。看看這個:https://developer.android.com/training/displaying-bitmaps/cache-bitmap.html#memory-cache – josemgu91

+0

鏈接描述了一個內存(RAM)緩存,但下面是一個磁盤緩存。你應該實現這兩個(RAM緩存速度更快但速度很慢,磁盤速度較慢但廣泛)。 – josemgu91