片段在启动时不执行AsyncTask

时间:2016-09-10 23:47:45

标签: java android android-fragments android-asynctask

当我的应用启动时,它会用片段替换布局,需要AsyncTask才能正确加载。当我从导航抽屉加载这个片段时,一切正常,但是它会在应用启动时加载,AsyncTask不会执行。我该如何解决这个问题?

MainActivity:

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);



    Fragment fragment = null;
    Class fragmentClass = null;
    fragmentClass = NewsFragment.class;
    try {
        fragment = (Fragment) fragmentClass.newInstance();

    } catch (Exception e) {
        e.printStackTrace();
    }

    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.frameLayoutForFragments, fragment);

    fragmentTransaction.commit();



    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);
    navigationView.getMenu().getItem(0).setChecked(true);
}

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}


@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) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    //Wybory elementów w navigationdrawer
    Fragment fragment = null;
    Class fragmentClass = null;
    int id = item.getItemId();

    if (id == R.id.nav_news) {
        fragmentClass = NewsFragment.class;

    } else if (id == R.id.nav_map) {
        fragmentClass = MapFragment.class;

    } else if (id == R.id.nav_buildings) {
        fragmentClass = BuildingsFragment.class;

    } else if (id == R.id.nav_manage) {
        fragmentClass = MapFragment.class;


    } else if (id == R.id.nav_info) {
        fragmentClass = AppInfoFragment.class;


    } else if (id == R.id.nav_bugreport) {
        fragmentClass = ContactFragment.class;

    }


    try {
        fragment = (Fragment) fragmentClass.newInstance();
    } catch (Exception e) {
        e.printStackTrace();
    }


    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction().replace(R.id.frameLayoutForFragments, fragment).commit();


    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

启动时加载的片段:

public class NewsFragment extends Fragment {

public static ArrayList <ParsedWebData> list = new ArrayList<ParsedWebData>();



public NewsFragment() {
    // Required empty public constructor
}


public static NewsFragment newInstance(Context context) {
    NewsFragment fragment = new NewsFragment();

    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Start AsyncTask w momencie ładowania fragmentu

    AsyncXMLParser parser = new AsyncXMLParser();
    parser.execute();


}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_news, container, false);

    ListView listView = (ListView) view.findViewById(R.id.listViewNews);

    CustomListViewAdapter customListViewAdapter = new CustomListViewAdapter(getContext(), R.id.listViewNews, list);
    listView.setAdapter(customListViewAdapter);

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> a, View v, int position, long id) {

            ParsedWebData singleData = list.get(position);
            String url = singleData.getUrl();

            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            startActivity(browserIntent);


        }
    });




    return view;
}

}

的AsyncTask:

public class AsyncXMLParser extends AsyncTask <Void, Integer, ArrayList<ParsedWebData>> {



    @Override
    protected void onPreExecute() {

    }

    @Override
    protected ArrayList<ParsedWebData> doInBackground(Void... params) {

        ArrayList<ParsedWebData> list = new ArrayList<ParsedWebData>();

        try {

            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            factory.setNamespaceAware(false);
            XmlPullParser xpp = factory.newPullParser();

            // We will get the XML from an input stream
            InputStream input = new URL("linkhere").openStream();
            xpp.setInput(input, "UTF_8");

            int eventType = xpp.getEventType();
            String text = null;
            ParsedWebData data = new ParsedWebData();

            while (eventType != XmlPullParser.END_DOCUMENT) {
                String tagname = xpp.getName();

                switch (eventType) {

                    case XmlPullParser.START_TAG:
                        if (tagname.equalsIgnoreCase("item")) {

                            data = new ParsedWebData();
                        }
                        break;

                    case XmlPullParser.TEXT:
                        text = xpp.getText();
                        break;

                    case XmlPullParser.END_TAG:
                        if (tagname.equalsIgnoreCase("item")) {
                            // add employee object to list
                            list.add(data);
                        } else if (tagname.equalsIgnoreCase("title")) {
                            data.title = text;
                        } else if (tagname.equalsIgnoreCase("link")) {
                            data.url = text;
                        } else if (tagname.equalsIgnoreCase("description")) {
                            text = Jsoup.parse(text).text();
                            data.description = text;
                        }
                        break;

                    default:
                        break;
                }
                eventType = xpp.next();



            }
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        NewsFragment.list = list;

        return list;
}

    @Override
    protected void onPostExecute(ArrayList <ParsedWebData> result) {

    }

}

我试图自己找到原因,并尝试在MainActivity中手动执行AsyncTask,但它没有帮助。任何想法有什么不对?

2 个答案:

答案 0 :(得分:2)

在OnCreateView运行之后,AsyncTask(线程)结束了,这是错误的,所以你看不到你的数据。
您可以做的是将代码行NewsFragment.list = list;doInBackground()移至onPostExecute(),然后调用adapter.notifyDataSetChanged()。但问题是,在您的设计中,您无法访问AsyncTask中的listView适配器 另外,将列表作为Fragment中的静态变量,以便您可以从AsyncTask访问它是非常糟糕的编程设计。 您应该删除静态列表变量,并重新设计AsyncTask,将listView传递给构造函数(您必须将它从onCreate移动到onCreateView),并将listView分配给AsyncTask中的成员。然后在onPostExecute中设置适配器(不在onCreateView中)

public class AsyncXMLParser extends AsyncTask <Void, Integer, ArrayList<ParsedWebData>> { 

    CustomListViewAdapter _adapter;

    Public AsyncXMLParser(CustomListViewAdapter adapter) {
       _adapter = adapter;
    }

   ...

    @Override 
    protected void onPostExecute(ArrayList <ParsedWebData> result) { 
        CustomListViewAdapter customListViewAdapter = new CustomListViewAdapter(getContext(), R.id.listViewNews, result);
        listView.setAdapter(customListViewAdapter); 
    // Or, depending on design
        _adapter.notifyDataSetChanged();
    }
}

这样,列表不是静态变量(可以从片段中删除代码),只有在AsyncTask完成后才会填充listView。如果您以后需要访问实际的列表数据,可以从适配器获取它。

答案 1 :(得分:0)

我找不到Asynctask为什么不被执行的原因但是根据你想要做多少背景工作,你可能不想使用 的AsyncTask。 Asynctask应仅用于执行花费少量时间(最多几秒)的操作,因为它的生命周期与ui组件的生命周期相关联。这里的问题很可能就是你要杀死asynctask因为它连接到了ui。

我建议您使用intentservice。它们非常易于使用,并且可以在后台运行。由于在这种情况下你似乎无法找到Asynctask的问题,你可能会通过使用intentservices来节省时间。 https://developer.android.com/reference/android/app/IntentService.html