Android Xml Pull Parser错误 - SitesDownloadTask.onPostExecute

时间:2014-07-30 15:55:39

标签: java android xml android-fragments android-arrayadapter

我的应用程序中有三个不同的Adapters和三个XML Parsers,用于在ViewPager上滑动三个片段。

我的应用程序正常工作,直到我开始在第一个和第二个,第二个和第三个片段之间滑动得更快一点。

Log Cat消息:

在第一和第二之间滑动时:

FATAL EXCEPTION: main
Process: com.intera.eronetmarket, PID: 3326
java.lang.NullPointerException
    at android.widget.ArrayAdapter.init(ArrayAdapter.java:310)
    at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:153)
    at adapters.KatAdapter.<init>(KatAdapter.java:32)
    at com.intera.eronetmarket.Kategorije$SitesDownloadTask.onPostExecute(Kategorije.java:98)
    at com.intera.eronetmarket.Kategorije$SitesDownloadTask.onPostExecute(Kategorije.java:1)
    at android.os.AsyncTask.finish(AsyncTask.java:632)
    at android.os.AsyncTask.access$600(AsyncTask.java:177)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5017)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
    at dalvik.system.NativeStart.main(Native Method)

在第二和第三之间滑动时:

FATAL EXCEPTION: main
Process: com.intera.eronetmarket, PID: 3359
java.lang.NullPointerException
    at com.intera.eronetmarket.Preporuceno$AppDownloadTask.onPostExecute(Preporuceno.java:85)
    at com.intera.eronetmarket.Preporuceno$AppDownloadTask.onPostExecute(Preporuceno.java:1)
    at android.os.AsyncTask.finish(AsyncTask.java:632)
    at android.os.AsyncTask.access$600(AsyncTask.java:177)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5017)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
    at dalvik.system.NativeStart.main(Native Method)

AppDownlodTask类的第一个片段。在所有3个片段中都是相同的(每个片段只有适配器不同):

public class Preporuceno extends Fragment  {

private AppAdapter mAdapter;
private ListView siteList;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i("mobAppModel", "OnCreate()");    
View rootView = inflater.inflate(R.layout.activity_preporuceno, container, false);


siteList = (ListView) rootView.findViewById(R.id.listView1);   

siteList.setOnItemClickListener(new OnItemClickListener(){

    @Override
    public void onItemClick(AdapterView<?> parent, View v, int pos,long id) {
        String url = mAdapter.getItem(pos).getstoreURL();
        Intent i = new Intent(Intent.ACTION_VIEW);
        i.setData(Uri.parse(url));
        startActivity(i);

    }
});

    if(isNetworkAvailable()){
        Log.i("mobAppModel", "starting download Task");
        AppDownloadTask download = new AppDownloadTask();
        download.execute();
    }else{
        mAdapter = new AppAdapter(getActivity().getApplicationContext(), -1, XMLsourcePullParser.getmobAppModel(getActivity()));
        siteList.setAdapter(mAdapter);
    }

    return rootView;
}

private boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager 
          = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnected();
} 
private class AppDownloadTask extends AsyncTask<Void, Void, Void>{
    @Override
    protected Void doInBackground(Void... arg0) {
        //Download the file
        try {
            Downloader.DownloadFromUrl("https://dl.dropboxusercontent.com/s/te0c0s7y7zr79tm/kategorijeXML.xml", getActivity().openFileOutput("XMLsource.xml", Context.MODE_PRIVATE));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return null;
    } 
    @Override
    protected void onPostExecute(Void result){
        //setup our Adapter and set it to the ListView.

        mAdapter = new AppAdapter(getActivity().getApplicationContext(), -1, XMLsourcePullParser.getmobAppModel(getActivity()));

            siteList.setAdapter(mAdapter);

        Log.i("mobAppModel", "adapter size = "+ mAdapter.getCount());
    }

}

}

我的适配器:

package adapters;

import java.util.List;
import models.KatModel;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.intera.eronetmarket.R;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;


/*
 * Custom Adapter class that is responsible for holding the list of sites after they
 * get parsed out of XML and building row views to display them on the screen.
 */
public class KatAdapter extends ArrayAdapter<KatModel> {

    ImageLoader imageLoader;
    DisplayImageOptions options;


    public KatAdapter(Context ctx, int textViewResourceId, List<KatModel> sites) {

        super(ctx, textViewResourceId, sites);

        //Setup the ImageLoader, we'll use this to display our images
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx).build();
        imageLoader = ImageLoader.getInstance();
        if (!imageLoader.isInited()) {
            imageLoader.init(config);
        }

        //Setup options for ImageLoader so it will handle caching for us.
        options = new DisplayImageOptions.Builder()
        .cacheInMemory()
        .cacheOnDisc()
        .build();}





    /*
     * (non-Javadoc)
     * @see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup)
     * 
     * This method is responsible for creating row views out of a StackSite object that can be put
     * into our ListView
     */
    @SuppressLint("InflateParams")
    @Override
    public View getView(int pos, View convertView, ViewGroup parent){
        RelativeLayout row = (RelativeLayout)convertView;
        Log.i("StackSites", "getView pos = " + pos);
        if(null == row){
            //No recycled View, we have to inflate one.
            LayoutInflater inflater = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = (RelativeLayout)inflater.inflate(R.layout.row_site, null);
        }

        //Get our View References

        TextView nameTxt = (TextView)row.findViewById(R.id.nameTxt);



        //Initially we want the progress indicator visible, and the image invisible




        //Load the image and use our options so caching is handled.


        //Set the relavent text in our TextViews
        nameTxt.setText(getItem(pos).getcategoryName());




        return row;


    }

}

-

package adapters;

import java.util.List;

import models.mobAppModel;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; 
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;

import com.intera.eronetmarket.R;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageLoadingListener;

@SuppressLint("InflateParams") public class AppAdapter extends ArrayAdapter<mobAppModel>{
    ImageLoader imageLoader;
    DisplayImageOptions options;
    public AppAdapter(Context ctx,int textViewResourceId, List<mobAppModel> appModel){
        super(ctx,textViewResourceId,appModel);

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx).build();
        imageLoader = ImageLoader.getInstance();
        if (!imageLoader.isInited()) {
            imageLoader.init(config);
         }



        options= new DisplayImageOptions.Builder()
        .cacheInMemory()
        .cacheOnDisc()
        .build();
    }

    public View getView(int pos, View convertView, ViewGroup parent){
        RelativeLayout row = (RelativeLayout)convertView;
        Log.i("mobAppModels", "getView pos = " + pos);
        if(null == row){
            //No recycled View, we have to inflate one.
            LayoutInflater inflater = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = (RelativeLayout)inflater.inflate(R.layout.row_app, null);
        }

        //Get our View References
        final ImageView iconImg = (ImageView)row.findViewById(R.id.iconUrl);
        final ProgressBar indicator = (ProgressBar)row.findViewById(R.id.progress);

        //Initially we want the progress indicator visible, and the image invisible
        indicator.setVisibility(View.VISIBLE);
        iconImg.setVisibility(View.INVISIBLE);

        //Setup a listener we can use to swtich from the loading indicator to the Image once it's ready
        ImageLoadingListener listener = new ImageLoadingListener(){



            @Override
            public void onLoadingStarted(String arg0, View arg1) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onLoadingCancelled(String arg0, View arg1) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
                indicator.setVisibility(View.INVISIBLE);
                iconImg.setVisibility(View.VISIBLE);
            }

            @Override
            public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
                // TODO Auto-generated method stub

            }

        };

        //Load the image and use our options so caching is handled.
        imageLoader.displayImage(getItem(pos).getimageUrl(),iconImg,options,listener);

        //Set the relavent text in our TextViews




        return row;


    }

}

-

package adapters;

import java.util.List;
import models.mobAppModel;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.RatingBar;
import com.intera.eronetmarket.R;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageLoadingListener;

public class AppAdapterNajpop extends ArrayAdapter<mobAppModel>{
    ImageLoader imageLoader;
    DisplayImageOptions options;
    public AppAdapterNajpop(Context ctx,int textViewResourceId, List<mobAppModel> appModel){
        super(ctx,textViewResourceId,appModel);

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx).build();
        imageLoader = ImageLoader.getInstance();
        if (!imageLoader.isInited()) {
            imageLoader.init(config);
         }


        options= new DisplayImageOptions.Builder()
        .cacheInMemory()
        .cacheOnDisc()
        .build();
    }

    @SuppressLint("InflateParams")
    public View getView(int pos, View convertView, ViewGroup parent){
        RelativeLayout row = (RelativeLayout)convertView;
        Log.i("mobAppModels", "getView pos = " + pos);
        if(null == row){
            //No recycled View, we have to inflate one.
            LayoutInflater inflater = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = (RelativeLayout)inflater.inflate(R.layout.row_app_najpopularnije, null);
        }

        //Get our View References
        final ImageView iconImg = (ImageView)row.findViewById(R.id.iconUrl);
        TextView appHeadline = (TextView)row.findViewById(R.id.textView1);
        TextView developer = (TextView)row.findViewById(R.id.textView2);
        RatingBar ratingpoints =(RatingBar)row.findViewById(R.id.ratingBar);
        final ProgressBar indicator = (ProgressBar)row.findViewById(R.id.progress);

        //Initially we want the progress indicator visible, and the image invisible
        indicator.setVisibility(View.VISIBLE);
        iconImg.setVisibility(View.INVISIBLE);

        //Setup a listener we can use to swtich from the loading indicator to the Image once it's ready
        ImageLoadingListener listener = new ImageLoadingListener(){



            @Override
            public void onLoadingStarted(String arg0, View arg1) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onLoadingCancelled(String arg0, View arg1) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
                indicator.setVisibility(View.INVISIBLE);
                iconImg.setVisibility(View.VISIBLE);
            }

            @Override
            public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
                // TODO Auto-generated method stub

            }

        };

        //Load the image and use our options so caching is handled.
        imageLoader.displayImage(getItem(pos).geticonUrl(),iconImg,options,listener);

        //Set the relavent text in our TextViews
        appHeadline.setText(getItem(pos).getappHeadline());
        developer.setText(getItem(pos).getdeveloper());
        ratingpoints.setRating(Float.parseFloat(getItem(pos).getratingPoints()));


        return row;


    }

}

当我滑得慢一点时,一切正常。怎么了? :\

1 个答案:

答案 0 :(得分:2)

当你从片段A快速翻转到B时,A可能随时被破坏,你无法控制它。在片段销毁过程完成之前,它也将与活动分离。从这一刻开始,任何来电getActivity()都可能会返回null

所以你的问题是你的片段没有对活动的引用,但异步任务仍然在后台线程中运行,导致空指针异常。

我建议你这样做:

Activity attached = getActivity();
if (attached != null) {
    mAdapter = new AppAdapter(attached.getApplicationContext(), -1, XMLsourcePullParser.getmobAppModel(getActivity()));
    siteList.setAdapter(mAdapter);
}

有关此问题的更多信息,请参见:http://developer.android.com/guide/components/fragments.html#Lifecycle。我想强调 Caution 会话:如果你需要Fragment中的Context对象,你可以调用getActivity()。但是,只有在片段附加到活动时才要小心调用getActivity()。当片段尚未附加或在其生命周期结束时被分离时,getActivity()将返回null。