質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

2回答

7565閲覧

取得した画像をgridViewで表示する際に、スレッドを使って高速化したい

nanshime_2621

総合スコア32

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2016/01/29 05:39

端末内に保存されている画像を取得して、gridViewを使ってサムネイル表示するコードを書きましたが、画像が多くなると、取得に時間がかかり、表示までかなり待たされる状態です。
スレッドを使って、画像を取得しながら同時に取得した画像を表示していくコードに書きかえたいと思っていますが、うまくコードにおとせません。

詳しい方がいらっしゃいましたらご教授お願いします。

MainActivity.java

package com.example.xx.gridlayout_3;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity implements AdapterView.OnItemClickListener {

private GridView mGridView = null; private List<String> imagePaths = new ArrayList<String>(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGridView = (GridView)findViewById(R.id.gridView1); //グリッド4列表示 mGridView.setNumColumns(4); //表示する画像を取得(DBへアクセス) Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; //SDカード //queryメソッドでカーソルを取得 Cursor cursor = getContentResolver().query(uri, null, null, null, null); ContentResolver cr = getContentResolver(); ArrayList<Bitmap> lstBitmap = new ArrayList<Bitmap>(); //カーソルの一番目に移動 cursor.moveToFirst(); for (int i = 0; i < cursor.getCount(); i++){ //画像iD取得 long id = cursor.getLong(cursor.getColumnIndexOrThrow("_id")); //画像パスを取得 imagePaths.add(cursor.getString(1)); //サムネイルを取得 Bitmap bmp = MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MICRO_KIND, null); lstBitmap.add(bmp); cursor.moveToNext();

// System.out.println(imagePaths);

} //アダプター作成 BitmapAdapter adapter = new BitmapAdapter(getApplicationContext(), lstBitmap); //グリッドにアダプタを設定 mGridView.setAdapter(adapter); //画像をクリックしたときの処理 mGridView.setOnItemClickListener(this); } @Override public void onItemClick(AdapterView<?> parent,View v,int position,long id){ Intent intent = new Intent(this.getApplicationContext(),SubActivity.class); String selectedImagePath = imagePaths.get(position); //「position」を、"imagePath"をキーワードにしてインテントにセット intent.putExtra("imagePath",selectedImagePath); //アクティビティをスイッチ startActivity(intent); }

}

BitmapAdapter.java

package com.example.xx.gridlayout_3;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.Image;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import java.util.List;
/**

  • Created by xx on 2015/12/16.

*/

/"implements Runnable"を追加/
public class BitmapAdapter extends ArrayAdapter<Bitmap> /*implements Runnable */{

//GridView内で画像を表示するために作成したレイアウト private static final int RESOURCE_ID = R.layout.grid_item; private LayoutInflater mInflater; public BitmapAdapter(Context context, List<Bitmap> objects) { super(context, RESOURCE_ID, objects); mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); }

// @Override
//public void run() {

@Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(RESOURCE_ID, null); } ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView); imageView.setImageBitmap(getItem(position)); return convertView; }

//}
}

SubActivity.java

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;

/**

  • Created by xx on 2015/12/16.

*/
public class SubActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub);

Intent intent = getIntent(); String imagePath = intent.getStringExtra("imagePath"); ImageView imageView = (ImageView)findViewById(R.id.selectedImage); Bitmap bmp = BitmapFactory.decodeFile(imagePath); imageView.setImageBitmap(bmp); }

}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

会員登録したばかりなので、不備があったらすみません。

一覧する情報だけは最初に取っておいて、画像のロードなど重いところだけ
非同期にするというのはよくやります。
こんな感じではどうでしょうか。

MainActivityではカーソルからの情報取得だけ行い、画像のロードは
BitmapAdapterのImageLoadTaskで行います。
なお、Bitmapのキャッシュ処理などは省いています。

MainActivity

java

1public class MainActivity extends Activity implements AdapterView.OnItemClickListener { 2 3 private GridView mGridView = null; 4 5 @Override 6 public void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 10 mGridView = (GridView) findViewById(R.id.gridView1); 11 12 //グリッド4列表示 13 mGridView.setNumColumns(4); 14 //表示する画像を取得(DBへアクセス) 15 Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; //SDカード 16 //queryメソッドでカーソルを取得 17 Cursor cursor = getContentResolver().query(uri, null, null, null, null); 18 ArrayList<Pair<Long,String>> targets = new ArrayList<Pair<Long,String>>(); 19 20 //カーソルの一番目に移動 21 cursor.moveToFirst(); 22 for (int i = 0; i < cursor.getCount(); i++) { 23 long id = cursor.getLong(cursor.getColumnIndexOrThrow("_id")); 24 targets.add(new Pair<Long, String>(Long.valueOf(id), cursor.getString(1))); 25 cursor.moveToNext(); 26 } 27 //アダプター作成 28 BitmapAdapter adapter = new BitmapAdapter(getApplicationContext(), targets); 29 //グリッドにアダプタを設定 30 mGridView.setAdapter(adapter); 31 32 //画像をクリックしたときの処理 33 mGridView.setOnItemClickListener(this); 34 } 35 36 @Override 37 public void onItemClick(AdapterView<?> parent, View v, int position, long id) { 38 Intent intent = new Intent(this.getApplicationContext(), SubActivity.class); 39 Pair<Long,String> item = (Pair<Long,String>)parent.getAdapter().getItem(position); 40 String selectedImagePath = item.second; 41 //「position」を、"imagePath"をキーワードにしてインテントにセット 42 intent.putExtra("imagePath", selectedImagePath); 43 //アクティビティをスイッチ 44 startActivity(intent); 45 } 46}

BitmapAdapter

java

1import android.content.ContentResolver; 2import android.content.Context; 3import android.graphics.Bitmap; 4import android.os.AsyncTask; 5import android.os.Handler; 6import android.provider.MediaStore; 7import android.util.Pair; 8import android.view.LayoutInflater; 9import android.view.View; 10import android.view.ViewGroup; 11import android.widget.ArrayAdapter; 12import android.widget.ImageView; 13 14import java.util.List; 15/** 16 * Created by xx on 2015/12/16. 17 */ 18public class BitmapAdapter extends ArrayAdapter<Pair<Long,String>> { 19 20 //GridView内で画像を表示するために作成したレイアウト 21 private static final int RESOURCE_ID = R.layout.grid_item; 22 23 private LayoutInflater mInflater; 24 private final ContentResolver resolver; 25 private final Handler handler; 26 27 public BitmapAdapter(Context context, List<Pair<Long,String>> objects) { 28 super(context, RESOURCE_ID, objects); 29 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 30 resolver = context.getContentResolver(); 31 handler = new Handler(); 32 } 33 34 @Override 35 public View getView(int position, View convertView, ViewGroup parent) { 36 if (convertView == null) { 37 convertView = mInflater.inflate(RESOURCE_ID, null); 38 } 39 ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView); 40 // TODO: imageViewにロード中的な画像を貼る 41 Pair<Long,String> item = getItem(position); 42 ImageLoadTask task = new ImageLoadTask(resolver, handler, imageView); 43 task.execute(item.first); 44 45 return convertView; 46 } 47 48 private static class ImageLoadTask extends AsyncTask<Long,Void, Pair<Long,Bitmap>> { 49 private final ImageView view; 50 private final ContentResolver resolver; 51 private final Handler handler; 52 53 ImageLoadTask(ContentResolver resolver, Handler handler, ImageView view) { 54 this.resolver = resolver; 55 this.view = view; 56 this.handler = handler; 57 view.setTag(this); 58 } 59 60 private boolean isTargetChanged() { 61 return view.getTag() != this; 62 } 63 64 @Override 65 protected void onPostExecute(final Pair<Long,Bitmap> pair) { 66 if (pair == null || pair.second == null) { 67 return; 68 } 69 if (isTargetChanged()) { 70 return; 71 } 72 Runnable r = new Runnable() { 73 @Override 74 public void run() { 75 view.setImageBitmap(pair.second); 76 } 77 }; 78 handler.post(r); 79 } 80 81 @Override 82 protected Pair<Long,Bitmap> doInBackground(Long... longs) { 83 if (isTargetChanged()) { 84 return null; 85 } 86 long id = longs[0].longValue(); 87 return new Pair<Long,Bitmap>(Long.valueOf(id), 88 MediaStore.Images.Thumbnails.getThumbnail(resolver, id, 89 MediaStore.Images.Thumbnails.MICRO_KIND, null)); 90 } 91 } 92}

投稿2016/05/28 17:42

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

とりあえずUIスレッドの進行を邪魔している処理を調べることから始めましょう。
実装方法(Tread、AsyncTask、AsyncTaskLoaderなど)はユーザーにどのように見せたいのかが決まらないと決定できないですね。

今回で言えば下記の処理を非同期にすべきでしょうね。

Java

1uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; //SDカード 2 //queryメソッドでカーソルを取得 3 Cursor cursor = getContentResolver().query(uri, null, null, null, null); 4 ContentResolver cr = getContentResolver(); 5 ArrayList<Bitmap> lstBitmap = new ArrayList<Bitmap>(); 6 //カーソルの一番目に移動 7 cursor.moveToFirst(); 8 for (int i = 0; i < cursor.getCount(); i++){ 9 //画像iD取得 10 long id = cursor.getLong(cursor.getColumnIndexOrThrow("_id")); 11 //画像パスを取得 12 imagePaths.add(cursor.getString(1)); 13 //サムネイルを取得 14 Bitmap bmp = MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MICRO_KIND, null); 15 lstBitmap.add(bmp); 16 cursor.moveToNext(); 17// System.out.println(imagePaths); 18 19}

投稿2016/01/29 06:16

yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nanshime_2621

2016/01/29 08:27

Threadを使用して、 MainActivity.javaを書き換え、SubThread.javaを追加しましたが、アプリが落ちてしまいます。 MainActivity.java package com.example.ohmura.gridlayout_3; import android.app.Activity; import android.content.ContentResolver; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.GridView; import java.util.ArrayList; import java.util.List; public class MainActivity extends Activity implements AdapterView.OnItemClickListener { public GridView mGridView = null; public List<String> imagePaths = new ArrayList<String>(); public ArrayList<Bitmap> lstBitmap; public ContentResolver content = getContentResolver(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGridView = (GridView)findViewById(R.id.gridView1); SubThread sub = new SubThread(); Thread th = new Thread(sub); th.run(); //アダプター作成 BitmapAdapter adapter = new BitmapAdapter(getApplicationContext(), lstBitmap); //グリッドにアダプタを設定 mGridView.setAdapter(adapter); mGridView.setOnItemClickListener(this); } @Override public void onItemClick(AdapterView<?> parent,View v,int position,long id){ Intent intent = new Intent(this.getApplicationContext(),SubActivity.class); String selectedImagePath = imagePaths.get(position); //「position」を、"imagePath"をキーワードにしてインテントにセット intent.putExtra("imagePath",selectedImagePath); //アクティビティをスイッチ startActivity(intent); } } SubThread.java package com.example.xx.gridlayout_3; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.content.ContentResolver; import com.google.android.gms.appindexing.Action; import com.google.android.gms.appindexing.AppIndex; import com.google.android.gms.common.api.GoogleApiClient; import java.util.ArrayList; /** * Created by xx on 2016/01/29. */ public class SubThread implements Runnable { /** * ATTENTION: This was auto-generated to implement the App Indexing API. * See https://g.co/AppIndexing/AndroidStudio for more information. */ private GoogleApiClient client; @Override public void run() { //グリッド4列表示 MainActivity main = new MainActivity(); main.mGridView.setNumColumns(4); //表示する画像を取得(DBへアクセス) Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; //SDカード //queryメソッドでカーソルを取得 //Cursor cursor = getContentResolver().query(uri, null, null, null, null); Cursor cursor = main.content.query(uri, null, null, null, null); // ContentResolver cr = getContentResolver(); ContentResolver cr = main.content; main.lstBitmap = new ArrayList<Bitmap>(); //カーソルの一番目に移動 cursor.moveToFirst(); for (int i = 0; i < cursor.getCount(); i++) { //画像iD取得 long id = cursor.getLong(cursor.getColumnIndexOrThrow("_id")); //画像パスを取得 main.imagePaths.add(cursor.getString(1)); Bitmap bmp = MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MICRO_KIND, null); main.lstBitmap.add(bmp); cursor.moveToNext(); } } }
yona

2016/01/29 08:42

アプリが落ちますではわかりません。ログを貼るべきです。 また、プログラム上でActivityをnewできるとどこかで学びましたか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問