导航抽屉异步任务

Posted

技术标签:

【中文标题】导航抽屉异步任务【英文标题】:Navigation Drawer AsyncTask 【发布时间】:2015-11-06 03:04:35 【问题描述】:

我想公开我的问题,我想知道如何解决它。 在我的应用程序中,我正在使用一个活动,进行简单的登录,启动一个 asyncTask。在这个任务结束时,用户被重定向到另一个活动,这是应用程序的主活动。后者的任务是管理导航抽屉及其片段。每个片段的内容必须使用从服务器检索的数据填充,并且导航抽屉设置默认片段 F1,在用户登录后显示。 现在的问题是:

如何恢复填充 fragment1 中包含的 listView 所需的数据?

我知道如何为 listView 实现适配器,但我不明白如何将 home Activity 与 Fragment F1 进行通信。我的意图是检索一个循环对话框(F1 中的内容)并在适配器所需的数据尚未恢复时运行它。

这里有一些代码:

public class LoginActivity extends ActionBarActivity 

     private Button loginButton;    
     private ProgressDialog progressDialog;   

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

        loginButton = (Button) findViewById(R.id.login_button);
        loginButton.setOnClickListener(new View.OnClickListener() 
             @Override
             public void onClick(View v) 
                 new Login().execute();
             
         ; 
     

        @Override
     public boolean onCreateOptionsMenu(Menu menu) 
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
     

     @Override
     public boolean onOptionsItemSelected(MenuItem item) 
        int id = item.getItemId();

        if (id == R.id.action_settings) 
            return true;
        

        return super.onOptionsItemSelected(item);
     

     private class Login extends AsyncTask<Void, Void, Void> 

         @Override
         protected void onPreExecute() 
            super.onPreExecute();
            progressDialog = new ProgressDialog(LoginActivity.this);
            progressDialog.setMessage("Login");
            progressDialog.setCancelable(false);
            progressDialog.show();
         

         @Override
         protected void onPostExecute(Void aVoid) 
            super.onPostExecute(aVoid);
            if (progessDialog.isShowing()) 
                progressDialog.dismiss();
            
            Intent intent = new Intent(getApplicationContext(), HomeActivity.class);
            Bundle bundle = new Bundle();
            intent.putExtras(bundle);
            startActivity(intent);
        

        @Override
        protected Void doInBackground(String... params) 
           // code to retrieve data. 
        
     

public class HomeActivity extends ActionBarActivity implements FragmentDrawer.FragmentDrawerListener 

   private Toolbar toolbar;
   private FragmentDrawer fragmentDrawer;

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

       toolbar = (Toolbar) findViewById(R.id.toolbar);
       setSupportActionBar(toolbar);
       getSupportActionBar().setDisplayShowHomeEnabled(false);

       fragmentDrawer = (FragmentDrawer) getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
       fragmentDrawer.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), toolbar);
       fragmentDrawer.setDrawerListener(this);

       // Here the problem!!!
       displayView(0);
   

   @Override
   public boolean onCreateOptionsMenu(Menu menu) 
      getMenuInflater().inflate(R.menu.menu_home, menu);
      return true;
   

   @Override
   public boolean onOptionsItemSelected(MenuItem item) 
      int id = item.getItemId();

      if (id == R.id.action_settings) 
          return true;
      

      return super.onOptionsItemSelected(item);
   

   private void displayView(int position) 
       switch (position) 
           case 0:
               Fragment fragmentOne = new FragmentOne();
               move(matchFragment);
               break;
           case 1:
               Fragment fragmentTwo = new FragmentTwo();
               move(teamFragment);
               break;
           case 2:
               Fragment fragmentThree = new FragmentThree();
               move(myTeamFragment);
               break;
           case 3:
                //other fragment....
        default:
            break;
      
   

   public void move (Fragment fragment) 
       if (fragment != null) 
           FragmentManager fragmentManager = getSupportFragmentManager();
           FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
           fragmentTransaction.replace(R.id.container_body, fragment, fragment.getClass().getSimpleName());
           fragmentTransaction.commit();
       
   

   @Override
   public void onDrawerItemSelected(View view, int position) 
      displayView(position);
   

public class FragmentOne extends Fragment 

    private ListView listView;
    private ArrayList<Info> infos; 
    private InfoAdapter infoAdapter;  

    public FragmentOne() 

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
    

    @Nullable
    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) 
        final View rootView = inflater.inflate(R.layout.fragment_match, container, false);

        listView = (ListView) rootView.findViewById(R.id.match_list_view);

        return rootView;
    

现在,我在哪里实现 AsyncTask 来检索适配器的数据?在片段或活动中? 如果是Activity,如何恢复fragment的view元素?

在此先感谢,抱歉英语不好。

【问题讨论】:

【参考方案1】:

第一个问题:

我不明白如何将家庭活动与 片段F1

您可以通过传递给 Fragment 构造函数的参数将信息从 HomeActivity 传递给 Fragment。因此,您可以调用Fragment fragmentOne = new FragmentOne(A a); 而不是Fragment fragmentOne = new FragmentOne();,其中a 是您要传递给片段的数据。当然,你需要在Fragment类中加入带参数的构造函数。

第二点:

现在,我在哪里实现 AsyncTask 来检索适配器的数据? 在片段或活动中?如果是Activity,我该怎么做 恢复fragment的view元素?

您可以在 onCreate() 中调用 AsynchTask 来为 listView...等加载数据。我更喜欢的另一个选择是使用加载器。请在此处http://developer.android.com/guide/components/loaders.html 查看有关加载程序的文档。它也有一个例子。

对于解释和示例,您可以按照以下 4 部分教程进行操作: http://www.androiddesignpatterns.com/2012/07/loaders-and-loadermanager-background.html.

【讨论】:

fragment的构造函数不能为空? @Rick91,我不是那个意思。我的意思是,如果您想将信息从 Activity 传递到 fragment ,一种方法是创建带有一些参数的非默认构造函数。您可以同时使用空构造函数(无论出于何种原因)。 我可以使用这样的东西:public static MyFragment newInstance(int someInt) MyFragment myFragment = new MyFragment(); Bundle args = new Bundle(); args.putInt("someInt", someInt); myFragment.setArguments(args); return myFragment; 能不能给我一个关于装载机的例子? 我不明白的是:在LoginActivity的AsyncTask完成后,你看到fragmentOne,我必须在哪里调用获取listView所需数据的方法? 这正是装载机将要处理的事情。您不再需要调用 AsyncTask。如果你实现了 LoaderManager.LoaderCallbacks 接口,你应该在 onCreateLoader() 方法中创建一个新的加载器来检索数据(从内容提供者、数据库或通过网络,...),并在 onLoadFinished() 方法中将数据填充到你的视图中。如果要异步加载数据,则查找 AsyncTaskLoader。我已经用教程的链接更新了我的答案。希望对您有所帮助。

以上是关于导航抽屉异步任务的主要内容,如果未能解决你的问题,请参考以下文章

异步任务后在 SwiftUI 中的正确导航方式

Android:正确停止异步任务

异步任务片段背景数据

导航抽屉片段 Sqlite

Spring Boot - 异步任务

同步任务和异步任务