【问题标题】:Android - no view result returned from AsyncTask after modifying activityAndroid - 修改活动后没有从 AsyncTask 返回查看结果
【发布时间】:2014-01-02 16:42:56
【问题描述】:

我正在尝试修改下面的活动以使用两个 AsyncTask。没有 AsyncTasks 的原始活动有效,它导致在列表视图的垂直列表中显示一个小缩略图列表。但是现在在我单击按钮后,视图就变成了空白。正如您在 onLoadClicked 方法中看到的那样,我注释掉的行只是几行,并且这些行已重新定位在各个 AsyncTask 的 onPostExecute 方法中。如果您能帮助我理解我看过的内容,我将不胜感激。这是我第一次尝试使用 AsyncTask。另外,我想稍后修改活动,以便至少在 downloadImagesTask 内部使用 onProgressUpdate 方法,以便缩略图在加载时一一显示,而不是最后一次全部显示,但我有难以理解如何将 publishProgress 和 onProgressUpdate 融入当前结构。但目前解决当前问题更为紧迫。但沿着这些思路进一步完善的建议会有所帮助。谢谢。

主要活动的源代码:

public class MainActivity extends ListActivity {

private ImageAdapter adapter;
List<String> urls; // test1

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

    this.adapter = new ImageAdapter(this);
    setListAdapter(adapter);
}

public void onLoadClicked(View view){
    // no need to trigger more than once
    view.setVisibility(View.GONE);

    // download the images and add them to the adapter
    //List<String> urls = downloadImageUrls(); // test1

    new DownloadImageUrlsTask().execute();
    if(urls != null){

        for(String url : urls){
            //Bitmap image = downloadImage(url); // test1
            new DownloadImageTask().execute(url);
            //adapter.addItem(image);
        }
    }
}

public List<String> downloadImageUrls(){
    HttpGet get = new HttpGet("http://www.reddit.com/r/aww.json");
    AndroidHttpClient client = AndroidHttpClient.newInstance("android");
    //DefaultHttpClient client = new DefaultHttpClient();
    try{
        final List<String> result = client.execute(get, new 
MyJsonResponseHandler());
        return result;
    }catch(ClientProtocolException e){
        e.printStackTrace();
    }catch(IOException e){
        e.printStackTrace();
    }finally{
        client.close();
    }
    return null;
}

private class DownloadImageUrlsTask extends AsyncTask<Void, Void, List<String>>{
    @Override

    protected List<String> doInBackground(Void...voids){
        return downloadImageUrls();
    }
    protected void onPostExecute(List<String> result){
        urls = result;
    }

    protected void onProgressUpdate(Void... values) {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);
    }

}

public Bitmap downloadImage(String url){
    try{

        URL u = new URL(url);
        InputStream is = u.openStream();
        Bitmap b = BitmapFactory.decodeStream(is);
        return b;
    }catch(MalformedURLException e){
        e.printStackTrace();
    }catch(IOException e){
        e.printStackTrace();
    }
    return null;
}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>{

    @Override
    protected void onProgressUpdate(Void... values) {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);
    }

    protected Bitmap doInBackground(String...urls){
        return downloadImage(urls[0]);
    }

    protected void onPostExecute(Bitmap result){
    //  ImageView img = (ImageView)findViewById(R.id.image);
    //  img.setImageBitmap(result);
        adapter.addItem(result);
    }


}

class ImageAdapter extends BaseAdapter{

    private List<Bitmap> images;
    private final Context context;

    public ImageAdapter(Context context){
        super();
        this.context = context;
        images = new ArrayList<Bitmap>();
    }

    public void updateImages(List<Bitmap> images){
        this.images = images;
        notifyDataSetChanged();
    }

    public int getCount(){
        return images != null ? images.size() : 0;
    }

    public Bitmap getItem(int position){
        return images != null ? images.get(position) : null;
    }

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


    public View getView(int position, View convertView, ViewGroup parent){
        final View view;
        if(convertView == null || !(convertView instanceof ImageView)){
            view = 
LayoutInflater.from(context).inflate(R.layout.image_view, null);

        }else{
            view = convertView;
        }

        final ImageView imageView = (ImageView) 
view.findViewById(R.id.image);
        imageView.setImageBitmap(getItem(position));

        return view;
    }

    public void addItem(Bitmap bitmap){
        images.add(bitmap);
        notifyDataSetChanged();
    }

}


static class MyJsonResponseHandler implements ResponseHandler<List<String>>{

    public List<String> handleResponse(HttpResponse response) throws 
ClientProtocolException, IOException{
        // Loop through the results and grab the thumbnail URLs
        String data = EntityUtils.toString(response.getEntity());
        ArrayList<String> results = new ArrayList<String>();
        try{
            JSONObject root = new JSONObject(data);
            JSONArray children = 
root.getJSONObject("data").getJSONArray("children");

            for(int i = 0; i < children.length(); i++){
                JSONObject result = children.getJSONObject(i);
                String thumb = 
result.getJSONObject("data").getString("thumbnail");
                results.add(thumb);

                // limit the results size to 6 in order to be nice 
to their servers
                if(results.size() >= 6) break;
            }
        }catch(JSONException e){
            e.printStackTrace();
        }

        return results;
    }
}


}

main.xml 布局的来源:

LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity" >


<!-- <ImageView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/image"/> -->

<ListView 
    android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"></ListView>

<Button 
    android:id="@+id/button1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Load Images"
    android:onClick="onLoadClicked"
    />

</LinearLayout>

image_view.xml 布局的来源:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >


<ImageView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/image"/>

</LinearLayout>

清单文件的来源:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.lesson11"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="8" />
    <!-- android:targetSdkVersion="17"  -->


<uses-permission android:name="android.permission.INTERNET"/>

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.example.lesson11.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

【问题讨论】:

  • "new DownloadImageUrlsTask().execute();" - 对execute() 的调用将立即返回,因为它是异步的(因此得名AsyncTask)。这意味着条件检查if(urls != null) 会立即被调用,而AsyncTask 不会完成它正在做的事情,所以urls 将永远是null
  • 谢谢!我将您指出的代码部分移到了 DownloadImageUrlsTask 的 onPostExecute 方法中,它起作用了:protected void onPostExecute(List result){ urls = result; if(urls != null){ for(String url : urls){ new DownloadImageTask().execute(url); } } }
  • 附言。如果您想获得答案的功劳,请复制您的注释作为答案,我会检查它,否则我会回答并给予您功劳并引导人们发表您的评论。
  • 好的,我已经扩展了我的评论作为答案。很高兴我能提供帮助。

标签: android listview android-asynctask imageview


【解决方案1】:

这是问题的根源……

new DownloadImageUrlsTask().execute();
if(urls != null){
    ...
}

对 execute() 的调用将立即返回,因为它是异步的(因此命名为 AsyncTask)。

结果是代码if(urls != null) 中的条件检查被立即调用,但AsyncTaskdoInBackground(...) 方法不会完成它正在做的事情,urls 将始终是null

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多