Android多线程预加载imageview(uri)

时间:2016-10-04 16:32:39

标签: java android multithreading android-layout

我编写了一个简单的程序来在列表视图中显示图像但是当我滚动列表时,它非常慢。 我想创建一个新的Thread来处理imageview的加载。 我在论坛和文档中阅读,但我无法理解,你可以在一个单独的线程上编写简单的代码,也许用asyntask来管理什么(在单独的线程中预加载图像并仅在何时显示加载)? (我打算不使用毕加索或其他)

现在在我的代码中,当我按下菜单项时,我将一个imageview(uri)添加到linearlayout。 这是我的代码:

MainActivity:

public class MainActivity extends AppCompatActivity {



ImageView image;
LinearLayout background;


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

    background=(LinearLayout)findViewById(R.id.ll);


}

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


    return true;
}



@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();
    if (id == R.id.action_settings) {


        //open gallery
        Intent i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        i.setType("image/* video/*");
         startActivityForResult(i, 0);





         return true;
    }
    return super.onOptionsItemSelected(item);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Here we need to check if the activity that was triggers was the Image Gallery.
    // If it is the requestCode will match the LOAD_IMAGE_RESULTS value.
    // If the resultCode is RESULT_OK and there is some data we know that an image was picked
    if (requestCode == 0 && resultCode == RESULT_OK && null != data) {
        // Let's read picked image data - its URI
        Uri selectedImage = data.getData();
        // Get the real path from the Uri
        // Let's read picked image path using content resolver  
        String[] filePathColumn = { MediaStore.Images.Media.DATA };

        Cursor cursor = getContentResolver().query(selectedImage,
                filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();



        image=new ImageView(getApplicationContext());

        image.setImageURI(selectedImage);


        background.addView(image);



    }

}
}

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.provathreadimmagini.MainActivity" >

              <ScrollView
                 android:id="@+id/s"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_above="@+id/linearLayout1"
                 android:layout_alignParentLeft="true"
                 android:layout_alignParentTop="true"
                  android:fillViewport="true"
                     >

                 <LinearLayout
                     android:id="@+id/ll"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:gravity="center"
                     android:orientation="vertical"
                      android:paddingBottom="20dp"  >



                 </LinearLayout>
             </ScrollView>


</RelativeLayout>

谢谢

1 个答案:

答案 0 :(得分:0)

  

这个想法是UI线程(应用程序的主线程)将   每次你想访问你的文件时都不会等待   搜索特定图像以加载它。

     

对于这种情况,您可以使用(例如)AsyncTask

     

AsyncTask允许您执行后台操作(在后台运行)   线程)不会导致UI线程冻结。

正如您在文档中看到的,您应该创建一个扩展AsyncTask的类:

// In this example first param (URL) indicates the parameter you want to pass. 
// The second param is the progress unit you want to publish while it is computing
// The third is the result you wish yo send to the UI thread
public class BackgroundTask extends AsyncTask<URL, Integer, Long> {

}

现在,您必须至少覆盖一个方法:

// Long, URL - as stated above
protected Long doInBackground(URL... urls) {

}

为了完成此操作,您可能需要扩展结果函数

// In this function you should call your UI thread to set the image 
protected void onPostExecute(Long result) {
     showDialog("Downloaded " + result + " bytes");
 }

对于您的示例,我建议您将onActivityResult代码移动到新的doInBackground方法中。

编辑:

在您的主要活动中:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    BackgroundTask task = new BackgroundTask(mImage);
    task.execute(data.getData());

在BackgroundTask类中:

protected Long doInBackground(Uri... uris) {
    String[] filePathColumn = { MediaStore.Images.Media.DATA };

    Cursor cursor = getContentResolver().query(uris[0],
            filePathColumn, null, null, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    String picturePath = cursor.getString(columnIndex);
    cursor.close();

    mImage.setImageURI(uris[0]);
}