有时,我正在构建的应用程序将耗尽内存或接收与字节有关的错误(例如,无法分配带有125240个空闲字节和122KB的2320024字节分配,直到OOM)。
该应用程序非常重要,依赖于将byte []转换为位图(一般不推荐我知道 - 但对于这个特定项目来说是必要的恶意)。我一直收到关于“在主线程上做得太多”的不断消息。当它崩溃时,源可以追溯到我的gridAdapter类,有时我的buildImage类(使用gridAdapter)
我意识到正确的方法是在另一个线程上运行进程,但是我一直遇到困难。当我试图在另一个线程上运行“fillGrid()”和“fillPartialGrid()”方法时 - 运行应用程序时没有任何内容出现。当我尝试在gridAdapter的getView方法中使用新线程时,我最终只得到了半个图像。此外,我甚至设法收到一个错误,指向我使用单独线程的位置(在buildImage中)。
如果有人能就如何改善表现提出一些建议,我将非常感激。
buildImage
public class buildImage extends AppCompatActivity {
private SimpleCursorAdapter adapter;
private ImageButton back;
ImageView buildContainer;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_build_image);
super.onCreate(savedInstanceState);
buildContainer = (ImageView) findViewById(R.id.fullSizeImage);
back = (ImageButton) findViewById(R.id.backButton);
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, 60 * 2* 1000L);
}
protected void onStart() {
super.onStart();
Intent i = getIntent();
if (i.hasExtra("position"))
{
final int position = i.getExtras().getInt("position");
int lto = i.getExtras().getInt("lto");
int location = i.getExtras().getInt("location");
final gridAdapter adapter = new gridAdapter(this, lto, location);
new Thread(new Runnable() {
@Override
public void run() {
final Bitmap buildImage = BitmapFactory.decodeByteArray(adapter.buildImages.get(position), 0, adapter.buildImages.get(position).length);
buildContainer.post(new Runnable() {
@Override
public void run() {
buildContainer.setImageBitmap(buildImage);
}
});
}
}).start();
} else
{
byte[] imageId = i.getByteArrayExtra("imageID");
Bitmap buildImage = BitmapFactory.decodeByteArray(imageId, 0, imageId.length);
buildContainer.setImageBitmap(buildImage);
}
}
}
gridAdapter
public class gridAdapter extends BaseAdapter {
private Context mContext;
private int isLto;
private int board;
public Cursor items;
public ArrayList<String> itemNames = new ArrayList<String>();
public ArrayList<byte[]> icons = new ArrayList<byte[]>();
public ArrayList<byte[]> buildImages = new ArrayList<byte[]>();
public gridAdapter(Context context, int lto, int location) {
mContext = context;
isLto = lto;
board = location;
fillGrid();
}
public gridAdapter(Context context, int location, boolean homePage) {
mContext = context;
isLto = 1;
board = location;
fillPartialGrid();
}
private void fillGrid() {
databaseHelper dbHelper = new databaseHelper(mContext);
SQLiteDatabase db = dbHelper.getReadableDatabase();
items = db.rawQuery("SELECT " + databaseHelper.ITEM_NAME + ", " + databaseHelper.ICON + ", " + databaseHelper.IMAGE + " FROM " + databaseHelper.TABLE_NAME + " where " + databaseHelper.LTO + " = " + isLto + " and " + databaseHelper.LOCATION + " = " + board + " ORDER BY " + databaseHelper.ITEM_NAME + " ASC", null);
items.moveToFirst();
int counter = 0;
while(!items.isAfterLast()) {
itemNames.add(items.getString(items.getColumnIndex(databaseHelper.ITEM_NAME)));
icons.add(items.getBlob(items.getColumnIndex(databaseHelper.ICON)));
buildImages.add(items.getBlob(items.getColumnIndex(databaseHelper.IMAGE)));
counter++;
items.moveToNext();
}
items.close();
db.close();
dbHelper.database.close();
}
private void fillPartialGrid() {
databaseHelper dbHelper = new databaseHelper(mContext);
SQLiteDatabase db = dbHelper.getReadableDatabase();
items = db.rawQuery("SELECT " + databaseHelper.ITEM_NAME + ", " + databaseHelper.ICON + ", " + databaseHelper.IMAGE + " FROM " + databaseHelper.TABLE_NAME + " where " + databaseHelper.LTO + " = " + isLto + " and " + databaseHelper.LOCATION + " = " + board + " ORDER BY " + databaseHelper.ITEM_NAME + " ASC LIMIT 3", null);
items.moveToFirst();
int counter = 0;
while(!items.isAfterLast()) { itemNames.add(items.getString(items.getColumnIndex(databaseHelper.ITEM_NAME)));
icons.add(items.getBlob(items.getColumnIndex(databaseHelper.ICON)));
buildImages.add(items.getBlob(items.getColumnIndex(databaseHelper.IMAGE)));
counter++;
items.moveToNext();
}
items.close();
db.close();
dbHelper.database.close();
}
@Override
public int getCount() {
return itemNames.size();
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public Object getItem(int position) {
return buildImages.get(position);
}
@Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater layout = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layout.inflate(R.layout.grid_item, parent, false);
TextView gridItemName = (TextView)view.findViewById(R.id.gridItemName);
ImageView iconContainer = (ImageView)view.findViewById(R.id.gridItemIcon);
gridItemName.setText(itemNames.get(position));
Bitmap iconBitmap = BitmapFactory.decodeByteArray(icons.get(position), 0, icons.get(position).length);
iconContainer.setImageBitmap(iconBitmap);
return view;
}
}
以及使用gridAdapter并导致buildImage的另一个活动的示例
public class lunchStandard extends AppCompatActivity {
private String release = Build.VERSION.RELEASE;
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.configure_icon:
Intent i = new Intent(this, preferences.class);
startActivity(i);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private int discriminator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lunch_standard);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setClipChildren(false);
toolbar.setNavigationIcon(R.drawable.back);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(lunchStandard.this, launch_activity.class);
startActivity(i);
}
});
GridView grid = (GridView) findViewById(R.id.lunchStandardGrid);
SharedPreferences preferences = getSharedPreferences("config", MODE_PRIVATE);
if(preferences.getInt("Location", 2) == 3) {
discriminator = 3;
} else if(preferences.getInt("Location", 2) == 2){
discriminator = 2;
}
if(discriminator == 2) {
setTitle("Main Boards Builds " + release);
} else if (discriminator == 3) {
setTitle("Speciality Builds " + release);
}
gridAdapter adapter = new gridAdapter(this, 0, discriminator);
grid.setAdapter(adapter);
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(lunchStandard.this, buildImage.class);
intent.putExtra("location", discriminator);
intent.putExtra("lto", 0);
intent.putExtra("position", position);
startActivity(intent);
}
});
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent i = new Intent(lunchStandard.this, midamcorp.com.burgerkingapp.preferences.class);
startActivity(i);
}
});
}
}
答案 0 :(得分:0)
我能够在您提供的代码中识别一些减速和内存密集区域。我会尝试列出你可以获得最大收益的问题。
答案 1 :(得分:0)
为什么不使用像Glide这样的图片加载库并让它处理加载过程?并且你永远不会得到OOM
错误。
它非常容易设置,只需在gradle.build
compile 'com.github.bumptech.glide:glide:3.7.0'
然后您需要做的就是
Glide
.with(Context)
.load(adapter.buildImages.get(position))
.into(buildContainer);
我参与了处理图像的多个应用程序,这是避免我知道OOM
的最佳方法。
希望有所帮助