当前位置: 首页 > 知识库问答 >
问题:

从活动接收数据时碎片崩溃

郭阳曜
2023-03-14

我有一个问题,我的活动正在进行一个网络调用,当网络调用完成时,它使用从调用中收到的JSON对象的数据对活动进行了一些更改,然后将对象传递给同一活动中的片段。这些碎片在一个台面上。

我有同样的问题,我在这里问了这个问题,但我似乎也有同样的问题,即使在没有改变任何重要的东西后,它有了一点作用。我只是添加了更多我想要更改的字段?

我遇到的问题是,如果我使用system.out.println(),它会打印出正确的数据。当我想用片段中收到的数据设置TextView时,应用程序就会崩溃,出现NullPointer。当我用Android studio中的debug调试它时,我设置的TextView由于某种原因总是为空。

执行初始网络调用的活动代码

  @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listings);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
handleIntent(getIntent());

}


private void handleIntent(Intent aIntent) {
if (aIntent != null) {

  String tradeType = aIntent.getStringExtra("itemType");
  String tradeId = aIntent.getStringExtra("itemId");

  presenter = new ItemPresenterImpl(this, ItemBuyNowActivity.this);   
  presenter.doListingServiceCall(tradeId); // <------- This is the where I send the Trade Id so I can do the network call.
} else {
  System.out.println("Intent is null in " + ItemBuyNowActivity.class.getSimpleName());
}

}

活动与演示者之间的接口:

public interface ItemPresenter {

void doListingServiceCall(String itemId);  //<------- Comes to this Interface

void doToolbarBackgroundImageCall(TradeItem aTradeItem);

}

实现演示者的类:

@Override
  public void doListingServiceCall(String aItemId) {  // <------- This is where the network call starts
    String homeURL = BobeApplication.getInstance().getWsURL() + mContext.getString(R.string.ws_url_item) + aItemId;
    BobeJSONRequest jsObjRequest = new BobeJSONRequest(Request.Method.GET, homeURL, null, this, this);
    VolleySingleton.getInstance().addToRequestQueue(jsObjRequest, "ListingRequest");
  }

  @Override
  public void doToolbarBackgroundImageCall(TradeItem aTradeItem) {
    ImageRequest request = new ImageRequest(aTradeItem.getItem().getImageUrl(),
            new Response.Listener<Bitmap>() {
              @Override
              public void onResponse(Bitmap bitmap) {
                Drawable drawable = new BitmapDrawable(mContext.getResources(), bitmap);
                mItemView.loadBackgroundImage(drawable);
              }
            }, 0, 0, null,
            new Response.ErrorListener() {
              public void onErrorResponse(VolleyError error) {
                mItemView.displayErrorMessage(VolleyErrorHelper.getErrorType(error, mContext) + " occurred downloading background image");
              }
            });
    VolleySingleton.getInstance().addToRequestQueue(request, "ListItemToolbarBackgroundImageRequest");
  }

  @Override
  public void onResponse(Object response) { 
    Gson gson = new Gson();
    TradeItem tradeItem = gson.fromJson(response.toString(), TradeItem.class);
    mItemView.populateListViews(tradeItem); // <------- This is the where I send the Object so the views in the activity can be manipulated
    doToolbarBackgroundImageCall(tradeItem);
  }

方法中处理

  @Override
public void populateListViews(TradeItem aTradeItem) {
  mOverviewPresenter = new OverviewPresenterImpl(new OverviewListItemFragment(), aTradeItem);
  OverviewListItemFragment.setData(aTradeItem);  //<------- This is the where I send the Object to the fragment so i can manipulate the views in the fragment
}
class TabAdapter extends FragmentPagerAdapter {
    public TabAdapter(FragmentManager fm) {
      super(fm);
    }

    @Override
    public Fragment getItem(int position) {
      Fragment fragment = null;

      if (position == 0) {
        fragment = new OverviewListItemFragment();
      }
      if (position == 1) {
        fragment = new DescriptionListItemFragment();
      }
      if (position == 2) {
        fragment = new ShippingListItemFragment();
      }
      if (position == 3) {
        fragment = new PaymentListItemFragment();
      }
      return fragment;
    }

    @Override
    public int getCount() {
      return 4;
    }

    @Override
    public CharSequence getPageTitle(int position) {
      if (position == 0) {
        return "Overview";
      }
      if (position == 1) {
        return "Description";
      }
      if (position == 2) {
        return "Shipping";
      }
      if (position == 3) {
        return "Payment";
      }
      return null;
    }
  }

接收数据的片段:

    public class OverviewListItemFragment extends Fragment implements OverviewView {

  private static TextView mOverViewHeading;

  public OverviewListItemFragment() {
  }

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

  @Nullable
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.overview_list_item_fragment, container, false);
    mOverViewHeading = (TextView) view.findViewById(R.id.frag_overview_heading_textview);
    return view;

  }

  @Override
  public void populateOverviewViews(final TradeItem aTradeItem) {
    System.out.println("Overview Trade Object title is:" + aTradeItem.getItem().getTradeTitle());  // <------- This is print statement works 100% but when I try setting mOverViewHeading to the text in aTradeItem.getItem().getTradeTitle() I get a Null pointer Exception.

  }

  public static void setData(TradeItem aTradeItem) {
    System.out.println("Overview Trade Object title is:" + aTradeItem.getItem().getTradeTitle());  // <------- This is print statement works 100% but when I try setting mOverViewHeading to the text in aTradeItem.getItem().getTradeTitle() I get a Null pointer Exception.
    mOverViewHeading.setText(aTradeItem.getItem().getTradeTitle());// <------- This is where it crashes and mOverViewHeading is still null at this point.
  }
}

编辑:对不起,我忘记了logcat:

02-05 17:08:21.554 30512-30512/com.example.app E/AndroidRuntime: FATAL EXCEPTION: main
                                                          java.lang.NullPointerException
                                                              at com.example.app.ui.fragments.OverviewListItemFragment.setData(OverviewListItemFragment.java:46)
                                                              at com.example.app.ui.activities.ItemBuyNowActivity.populateListViews(ItemBuyNowActivity.java:95)
                                                              at com.example.app.listing.ItemPresenterImpl.onResponse(ItemPresenterImpl.java:62)
                                                              at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:65)
                                                              at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
                                                              at android.os.Handler.handleCallback(Handler.java:725)
                                                              at android.os.Handler.dispatchMessage(Handler.java:92)
                                                              at android.os.Looper.loop(Looper.java:137)
                                                              at android.app.ActivityThread.main(ActivityThread.java:5041)
                                                              at java.lang.reflect.Method.invokeNative(Native Method)
                                                              at java.lang.reflect.Method.invoke(Method.java:511)
                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
                                                              at dalvik.system.NativeStart.main(Native Method)

共有1个答案

许典
2023-03-14

overviewListItemFragment我假设这不是添加的片段实例,而是类。

我建议进行以下更改:从setdata和您的textview中删除static,如果您确实知道它是如何工作的,请保留它。我认为这没有必要,也不值得推荐。

private OverviewListItemFragment mFrag; //declare globally

mFrag = new OverviewListItemFragment(); 
//if you do not want to add it now, ignore the following line
getSupportFragmentManager().beginTransaction().add(R.id.yourContainer, mFrag, "mFrag").commit();

现在,每次要设置数据时,调用mfrag.setdata。检查mfrag是否为null,然后重新初始化,可能重新添加,或者执行任何您想要执行的操作。

编辑:既然我知道您使用的是viewpager,我建议您执行以下操作:

执行上述操作。我认为在这个context中使用静态方法是不可取的。由于试图访问片段中的TextView,因此会出现错误。这是在ViewPager/PagerAdapter中初始化的,PagerAdapter保存对片段的已用实例的引用。您可以通过以下方式访问已使用的片段

 Fragment mFragment = pagerAdapter.getFragment(0); //frag at position 0

通过一些选角,您将能够找到您的(现在不是静态的)方法:

((OverviewListItemFragment)pagerAdapter.getFragment(0)).setData(YOUR_DATA);

请添加一些try/catch。检查您的片段是否为null,因为您的片段有可能在FragmentPagerAdapter中被回收,因为它达到了偏移量。实现这一点的另一种方法是存储所需的数据,并在每次片段可见时更新它,如本文所述。

编辑2:显然,您需要在适配器中进行一些更改:

我建议在构造html" target="_blank">函数中创建一个包含片段的数组:

//global in your adapter:
private Fragment[] fragments;

public CustomPagerAdapter(FragmentManager fm) {
        super(fm);
        fragments = new GameFragment[4];
        fragments[0] = new MyFragment();
        fragments[1] = new SecondFragment();
        ....
    }
    public Fragment getItem(int position) {
       return fragments[position];
    }

    public Fragment getFragment(int position) {
       return fragments[position];
    }
 类似资料:
  • 我可以使用一个片段作为一个活动吗?我已经创建了一个片段,但我希望它有像活动一样的功能,所以我使用片段扩展碎片活动。然而,我有一个带有碎片的导航抽屉。当我更改为“扩展碎片活动”时,我的代码有问题?请给我指路。

  • 我一直对此感到沮丧,也找不到好的答案,所以希望这里有人能提供指导。 我有一个片段相当广泛地使用了。片段调用(返回null)时,我经常受到错误的困扰。我假设发生这些情况是因为在附加活动之前或分离活动之后调用了片段中的某些方法。 在我的代码中处理这个问题的正确方法是什么?我不想让这个成语到处乱扔, 一些人建议在暂停时取消任务,但这意味着标准习惯用语, 无法使用。这意味着每个执行的都需要跟踪到完成或取消

  • 由于不推荐使用TabActivity,我需要找到一种方法来使用片段。在我知道它如何工作之前,我已经使用了碎片,但我需要一个指南来创建我的标签主机与碎片活动。我在互联网上找到了几个例子,它们都是关于将片段放入标签的容器中的。

  • 我是Android新手。我想建立一个标签格式的应用程序。我找到了许多使用了活动的文档。在许多情况下,还使用了碎片活动。我不确定从哪一个开始更好。请建议我是否应该使用或以选项卡格式开始开发?

  • 我读过很多关于这方面的文章,但也有2012年或更早的文章。 (我只是打算从数据库中读取和插入一些数据。)

  • 我有一个托管3个片段的活动,我的活动包含一些我希望我的第一个片段使用的数据。我尝试调用以下方法,以便活动可以与片段通信: 对于活动类和: 对于fragment类,但它在运行时对空对象引用错误调用虚拟方法“void com.tex.lightweatherforecast.FirstFragment.doSomething(java.lang.String)”。 我的活动代码是: 任何帮助将不胜感激