美好的一天,
我遇到的问题是我的活动正在进行网络呼叫,当网络呼叫完成时,它会使用来自呼叫的JSON对象的数据对活动进行一些更改,然后将对象传递给同一活动中的碎片。这些片段位于TabLayout中。
我遇到了同样的问题,我在这里问at this SO Question这样就解决了问题,但我似乎也遇到了同样的问题,即使它在没有改变任何重要事项之后有所作为。我只是添加了我想要更改的更多字段?
我遇到的问题是,如果我放入System.out.println(),它会打印出正确的数据。我想要设置的那一分钟用我在片段中收到的数据说明TextView应用程序崩溃与Nullpointer。当我使用Android Studio中的Debug调试它时,由于某种原因,TextView I设置始终为null。
执行初始网络呼叫的活动代码:
@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);
}
实现Presenter的实现:
@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);
}
处理
的Activity中的方法 @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)
我的想法是,我尝试设置的视图在接收数据时不是“活动”(如果那是正确的词),因为当我在方法上运行带有断点的调试器时接收片段中的数据,mOverViewHeading TextView id为null,即使我在onCreate中有findViewById,也尝试将它放在onCreateView()中但两次都失败了。我还尝试将findViewById置于响应成功但在我尝试在TextView上设置setText()之前调用的相同方法中。
谢谢
答案 0 :(得分:1)
OverviewListItemFragment
我认为这不是你添加的片段实例,而是类。
我建议您进行以下更改:从static
和setData
删除TextView
,如果您确实知道它是如何工作的,请将其保留。我不认为这是必要的或值得推荐的。
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
是否为空,然后重新初始化,可能重新添加,或者您想要做什么。
编辑:既然我知道你使用的是ViewPager
,我建议如下:
做到以上几点。我不认为在Context
中使用静态方法是值得推荐的。您收到错误是因为您尝试在TextView
中找到Fragment
。这是在ViewPager
/ PagerAdapter
中初始化的,PagerAdapter
包含对已使用的片段实例的引用。
您可以通过
Fragment mFragment = pagerAdapter.getFragment(0); //frag at position 0
通过一些演员,你将能够找到你的(现在不是静态的)方法:
((OverviewListItemFragment)pagerAdapter.getFragment(0)).setData(YOUR_DATA);
请添加一些try/catch
。检查您的片段是否为null
,因为您的片段可能会在FragmentPagerAdapter
中回收,因为它已达到偏移量。另一种实现此目的的方法是存储您所需的数据,并在每次片段可见时更新它,如here所述。
编辑2:显然,您需要在Adapter
中进行一些更改:
我建议在构造函数中创建一个包含片段的数组:
//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];
}