在应用程序完成获取并将获取的数据传递给它之后,我应该如何启动一个新的 Activity?

Posted

技术标签:

【中文标题】在应用程序完成获取并将获取的数据传递给它之后,我应该如何启动一个新的 Activity?【英文标题】:How should I start a new Activity, after the application is done fetching and passing the fetched data to it? 【发布时间】:2020-08-04 02:02:38 【问题描述】:

在我的应用程序中,我使用联系人数据库并使用 RecyclerView 显示这些联系人。当我点击一个联系人时,我想从数据库中的表中获取它的数据,并将它们加载到一个新的活动中,ContactCard。我有一个 AsyncTask(),它获取与所选 contactId 匹配的 PhoneNumber 对象,但我还需要从其他表中检索 AddressEmail 对象。

我希望能够在获取所有相关数据后启动活动,我尝试在联系人RecyclerView 的活动中执行此操作,但由于尚未获取数据,应用程序崩溃了。

我可以使用 Intent 调用新 Activity,但如何确保在启动新 Activity(有效显示此数据)之前先获取来自不同表的数据?

我的一些代码:

public class PhoneNumberRepository 

    private WorksideDatabase worksideDatabase;
    private List<PhoneNumber> returnedNumbers;
    private Context mContext;

    public PhoneNumberRepository(Context context) 
        String DB_NAME = "workside_database";
        worksideDatabase = Room.databaseBuilder(context, WorksideDatabase.class, DB_NAME).build();
        mContext = context;
    

    public List<PhoneNumber> fetchPhoneNumbers(final int id) 

        new AsyncTask<Integer, Void, List<PhoneNumber>>() 
            @Override
            protected List<PhoneNumber> doInBackground(Integer... ids) 

                returnedNumbers = worksideDatabase.phoneNumberDao().getPhoneNumbersById(id);

                System.out.println(returnedNumbers);

                for (PhoneNumber pn : returnedNumbers) 
                    System.out.println("Number: " + pn.getPhoneNumber());
                

                return returnedNumbers;
            

            // This runs in UI when background thread finishes
            @Override
            protected void onPostExecute(List<PhoneNumber> result) 
                super.onPostExecute(result);

                System.out.println("Entered onPostExecute of fetchPhoneNumbers");

                //                for (PhoneNumber pn : result) 
                //                    Toast.makeText(mContext, pn + "", Toast.LENGTH_SHORT).show();
                //                
            
        .execute();

        return returnedNumbers;
    

    public List<PhoneNumber> getPhoneNumbers(int id) 
        return fetchPhoneNumbers(id);
    

联系人片段:

     adapter.setOnItemClickListener(
                contact -> 
     Intent viewContact = new Intent(getActivity(), WorksideContactCard.class);
     viewContact.putExtra(WORKSIDE_CONTACT, contact);

     PhoneNumberRepository phoneNumberRepository =
         new PhoneNumberRepository(getActivity().getApplicationContext());

     List<PhoneNumber> phoneNumberList;

     phoneNumberList = phoneNumberRepository.getPhoneNumbers(contact.getId());

     ArrayList<PhoneNumber> arrlistPhoneNumbers =
                                new ArrayList<>(phoneNumberList);
                        viewContact.putParcelableArrayListExtra(
                                WORKSIDE_CONTACT_PHONE_NO, arrlistPhoneNumbers);

      startActivity(viewContact);

【问题讨论】:

从 logcat 发布崩溃日志 @karan 好吧,我已经解决了这个问题。本质上,我在 AsyncTask() 完成获取数据之前尝试使用 List 变量。 那么你的问题得到解答了吗? @karan 道歉,我重新表述了我的问题以使其更清楚。在开始新活动之前,我需要确保首先获取来自不同表的数据。 【参考方案1】:

您可以在单击一个项目时执行此操作,像这样启动异步任务

 adapter.setOnItemClickListener(
                contact -> 
     PhoneNumberRepository phoneNumberRepository =
     new PhoneNumberRepository(getActivity().getApplicationContext());

 List<PhoneNumber> phoneNumberList;

 phoneNumberRepository.getPhoneNumbers(contact.getId());


并将您的 PhoneNumberRepository 更改为此类

public class PhoneNumberRepository 

        private WorksideDatabase worksideDatabase;
        private List<PhoneNumber> returnedNumbers;
        private Context mContext;

        public PhoneNumberRepository(Context context) 
            String DB_NAME = "workside_database";
            worksideDatabase = Room.databaseBuilder(context, WorksideDatabase.class, DB_NAME).build();
            mContext = context;
        

        public void fetchPhoneNumbers(final int id) 

            new AsyncTask<Integer, Void, List<PhoneNumber>>() 
                @Override
                protected List<PhoneNumber> doInBackground(Integer... ids) 

                    returnedNumbers = worksideDatabase.phoneNumberDao().getPhoneNumbersById(id);

                    System.out.println(returnedNumbers);

                    for (PhoneNumber pn : returnedNumbers) 
                        System.out.println("Number: " + pn.getPhoneNumber());
                    

                    return returnedNumbers;
                

                // This runs in UI when background thread finishes
                @Override
                protected void onPostExecute(List<PhoneNumber> result) 
                    super.onPostExecute(result);
 Intent viewContact = new Intent(context, WorksideContactCard.class);
    ArrayList<PhoneNumber> arrlistPhoneNumbers =
                                new ArrayList<>(result);
                        viewContact.putParcelableArrayListExtra(
                                WORKSIDE_CONTACT_PHONE_NO, arrlistPhoneNumbers);

      context.startActivity(viewContact);
                    System.out.println("Entered onPostExecute of fetchPhoneNumbers");


                
            .execute();

        

        public void getPhoneNumbers(int id) 
            return fetchPhoneNumbers(id);
        
    

【讨论】:

是的,这可能就是我需要做的。在onPostExecute 中创建意图,并在其中获取联系人、电话号码、电子邮件和地址对象的数据,然后再显示联系人的数据。【参考方案2】:

将联系人存储在 doInBackground() 方法中的列表中,并在 onPostExecute() 中启动新活动的意图 em> 方法,并使用此意图将联系人列表作为 intent.extra() 变量传递,检索并在调用的活动中使用它们。

【讨论】:

【参考方案3】:

将您的存储库类更改为类似的内容

public class PhoneNumberRepository 

    private WorksideDatabase worksideDatabase;
    private List<PhoneNumber> returnedNumbers;
    private Context mContext;
    private boolean dataDownloaded;

    public PhoneNumberRepository(Context context) 
        String DB_NAME = "workside_database";
        worksideDatabase = Room.databaseBuilder(context, WorksideDatabase.class, DB_NAME).build();
        mContext = context;
    

    public List<PhoneNumber> fetchPhoneNumbers(final int id) 

        new AsyncTask<Integer, Void, List<PhoneNumber>>() 
            @Override
            protected List<PhoneNumber> doInBackground(Integer... ids) 

                returnedNumbers = worksideDatabase.phoneNumberDao().getPhoneNumbersById(id);

                System.out.println(returnedNumbers);

                for (PhoneNumber pn : returnedNumbers) 
                    System.out.println("Number: " + pn.getPhoneNumber());
                

                return returnedNumbers;
            

            // This runs in UI when background thread finishes
            @Override
            protected void onPreExecute(List<PhoneNumber> result) 
                //set flag to false when download starts
               dataDownloaded = false;
             

            // This runs in UI when background thread finishes
            @Override
            protected void onPostExecute(Object obj) 
                super.onPostExecute(result);

                //set flag to true once download completes, you can also check if response is null and update it accordingly 
                dataDownloaded = true;

                System.out.println("Entered onPostExecute of fetchPhoneNumbers");

                //                for (PhoneNumber pn : result) 
                //                    Toast.makeText(mContext, pn + "", Toast.LENGTH_SHORT).show();
                //                
            
        .execute();

        return returnedNumbers;
    

    public List<PhoneNumber> getPhoneNumbers(int id) 
        return fetchPhoneNumbers(id);
    

    public boolean isDataDownloaded(int id) 
        return dataDownloaded;
    

onItemClick()中使用此功能,无论您的数据是否下载

if(phoneNumberRepository.isDataDownloaded()) 
   //code to fetch data from phonenumberrepo and start activity

【讨论】:

目前我对获取空联系人没有任何问题。出现问题是因为我有单独的联系人表格,以及存储在单独表格中的“电话号码”、“电子邮件”和“地址”等信息。检索联系人本身是可以的,但我还需要检索相关的电话号码、电子邮件和地址。 @George 是来自本地数据库的数据吗? 是的,并且存储库类正确地获取数据。 嗯好吧,但是如果我在onItemClick() 中调用if(phoneNumberRepository.isDataDownloaded()),它肯定会在获取数据之前执行,因此dataDownloaded 将始终为false?如果您不相信,我可以试一试。 您可以显示正在下载数据的相应消息,当下载完成并且用户点击项目时,它将带他进入下一个带有数据的活动。

以上是关于在应用程序完成获取并将获取的数据传递给它之后,我应该如何启动一个新的 Activity?的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序如何将接口获取的数据传递给自定义组件

如何使用 IOCP 将用户定义的数据传递给工作线程?

如何将解析器中的数据传递给函数

将数据传递给 Web 服务获取 - 500(内部服务器错误)

当我的应用程序通过我的 UITabBar 完成启动时,如何将加载的数据传递给 UITableView?

提交表单并将数据传递给 FileStreamResult 类型的控制器方法