[英]Intent putExtra() not working
Hi in my MainActivity
I implemented ViewPager
with TabLayout
with 3 tabs and each view page starts new Fragment. 嗨,在
MainActivity
我实现了带有3个标签的ViewPager
的TabLayout
,并且每个视图页面都开始了新的Fragment。 I am showing cards in a grid view in each Fragment and when a card is clicked DetailActivtiy
starts. 我在每个片段的网格视图中显示卡片,并且单击
DetailActivtiy
时, DetailActivtiy
开始。 I am starting detail activity from Fragments but when I try to put some extra in Intent
starting detail activity I get NullPointerException
. 我从Fragments开始细节活动,但是当我尝试在
Intent
开始细节活动中添加一些额外内容时,我得到NullPointerException
。 I tried to debug code but I am unable to find where the problem is. 我尝试调试代码,但是找不到问题所在。
Here's my code: 这是我的代码:
PopularFragment
(one of the tab layout in 3 tabs) PopularFragment
(3个选项卡中的一个选项卡布局)
public class PopularFragment extends Fragment implements PosterTask.GetPoster,RecyclerAdapter.OnClick {
private RecyclerAdapter mRecyclerAdapter;
private ProgressDialog mProgressBar;
private ArrayList<Movie> movies;
public PopularFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_popular, container, false);
//Show progress bar
showProgressBar();
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
//Setting layout manager
recyclerView.setLayoutManager(new GridLayoutManager(inflater.getContext(), 2));
//Setting adapter
mRecyclerAdapter = new RecyclerAdapter(inflater.getContext());
recyclerView.setAdapter(mRecyclerAdapter);
return view;
}
@Override
public void onStart() {
super.onStart();
//Starting asyncTask
new PosterTask(this).execute(buildUrl().toString());
//Setting listener to cards
mRecyclerAdapter.setOnClickListener(this);
}
//Building url
private Uri buildUrl(){
//Building url
String api_key = "api_key";
return Uri.parse(Utility.POPULAR_URL).buildUpon()
.appendQueryParameter(api_key, getString(R.string.API_KEY))
.build();
}
//Called after getting posters url's
@Override
public void onPosterCompleted(ArrayList<Movie> movies) {
ArrayList<String> poster = new ArrayList<>();
for(int i=0;i<movies.size();i++){
poster.add(movies.get(i).getPoster());
}
//Passing data to adapter
mRecyclerAdapter.setPoster(poster);
//Removing progress bar
mProgressBar.hide();
this.movies = movies;
}
//Showing progress bar
private void showProgressBar(){
mProgressBar = new ProgressDialog(getContext());
mProgressBar.setMessage("Fetching data...");
mProgressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressBar.show();
}
@Override
public void onClicked(int position, View v) {
//Starting detail activity
Intent intent = new Intent(getActivity(), DetailActivity.class);
intent.putExtra(Utility.INTENT_CONSTANT, "sahil");
startActivity(intent);
}
}
Here onClicked()
method is called when any card of RecyclerView
is clicked. 单击任何
RecyclerView
卡时,将调用onClicked()
方法。 RecyclerAdapter
: RecyclerAdapter
:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private Context mContext;
private ArrayList<String> mPosters;
private static OnClick mListener;
//Listener listening clicks
public interface OnClick{
void onClicked(int position, View v);
}
public RecyclerAdapter(Context context){
mContext = context;
}
//Set poster url
public void setPoster(ArrayList<String> poster){
mPosters = poster;
notifyDataSetChanged();
}
//Set listener
public void setOnClickListener(OnClick listener){
mListener = listener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.card_layout, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//Loading url images to image view in cards
Picasso.with(mContext).load(mPosters.get(position)).into(holder.imageView);
}
@Override
public int getItemCount() {
if(mPosters!=null) {
return mPosters.size();
}
return 0;
}
//View holder for adapter
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private ImageView imageView;
public ViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.card_image);
imageView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
mListener.onClicked(getPosition(), v);
}
}
}
When I start DetailActivity
without putting extra in Intent
it works but when I put extra in Intent
and try to retrieve it in DetailActivity
I get NullPointerException
. 当我在没有在
Intent
额外DetailActivity
情况下启动DetailActivity
,它可以工作,但是当我在Intent
额外内容并尝试在DetailActivity
检索它时,我得到了NullPointerException
。 In DetailFragment
(contained by DetailActivity
i try to get intent as): 在
DetailFragment
(由DetailActivity
包含,我尝试以此为意图):
//Exception:Detailfragment:
public class DetailFragment extends Fragment implements TrailerRecyclerAdapter.OnClick,TrailerTask.TrailerCompleted {
@Bind(R.id.movie_title)TextView titleView;
@Bind(R.id.movie_date)TextView dateView;
@Bind(R.id.movie_image)ImageView imageView;
@Bind(R.id.movie_vote_avg)TextView voteView;
@Bind(R.id.movie_votes)TextView totalView;
@Bind(R.id.favorite_button)Button favButton;
@Bind(R.id.trailer_view)RecyclerView trailerView;
@Bind(R.id.review_view)RecyclerView reviewView;
private TrailerRecyclerAdapter mTrailerAdapter;
private ArrayList<String> mTrailers;
public DetailFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_detail, container, false);
//Binding views
ButterKnife.bind(this, view);
//Getting clicked movie
// Movie movie = getActivity().getIntent().getParcelableExtra(Utility.INTENT_CONSTANT);
//Starting asyncTask
// new TrailerTask(this).execute(movie.getId());
//Binding data
// bindData(movie);
Log.v("title", getActivity().getIntent().getStringExtra(Utility.INTENT_CONSTANT));
return view;
}
//Binds data to views
/*
private void bindData(Movie movie){
titleView.setText(movie.getTitle());
dateView.setText(movie.getDate());
Picasso.with(getContext()).load(movie.getBack_poster()).into(imageView);
voteView.setText(String.valueOf(movie.getVote_avg()));
String total = getString(R.string.before) + movie.getTotal_votes() + getString(R.string.after);
totalView.setText(total);
//Setting adapter to trailerView
mTrailerAdapter = new TrailerRecyclerAdapter(getContext());
trailerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
trailerView.setAdapter(mTrailerAdapter);
}
*/
@Override
public void onClicked(int position, View v) {
//Building intent
Uri uri = Uri.parse(mTrailers.get(position)).buildUpon().build();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivity(intent);
}
}
@Override
public void onTrailerCompleted(ArrayList<String> trailers, ArrayList<String> trailer_posters) {
mTrailers = trailers;
mTrailerAdapter.setPoster(trailer_posters);
}
}
Here's the Github repo 这是Github回购
Logcat: Logcat:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.movies, PID: 14578
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.movies/com.example.android.movies.DetailActivity}: android.view.InflateException: Binary XML file line #1: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2338)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:816)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:745)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
at com.example.android.movies.DetailActivity.onCreate(DetailActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5292)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1088)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2302)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.v(Log.java:118)
at com.example.android.movies.DetailFragment.onCreateView(DetailFragment.java:54)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1036)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1226)
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1328)
at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2284)
at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:111)
at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:314)
at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:31)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:816)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:745)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
at com.example.android.movies.DetailActivity.onCreate(DetailActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5292)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1088)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2302)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(Native Method)
You should not be using a static variable to hold the callback listener in your RecyclerAdapter
. 您不应使用静态变量将回调侦听器保存在
RecyclerAdapter
。 This means each RecyclerAdapter
will always have the same callback listener when you want each one to have its own. 这意味着当您希望每个
RecyclerAdapter
具有自己的回调侦听器时,它们将始终具有相同的回调侦听器。
That is why you are experiencing this issue. 这就是为什么您遇到此问题的原因。
RatedFragment
and PopularFragment
are both using a RecyclerAdapter
. RatedFragment
和PopularFragment
都使用RecyclerAdapter
。 When you click an image the callback from your RatedFragment
will be called even when viewing the PopulareFragmnet
. 当您单击图像时,即使查看
PopulareFragmnet
也会调用RatedFragment
的回调。
RatedFragment
is then not adding the extra you are looking for which is causing the NullPointerException
. 然后,
RatedFragment
不会添加您正在寻找的导致NullPointerException
的额外内容。
To fix this remove static from mListener in the RecyclerAdapter
: 为了解决这个问题,从mListener消除静电的
RecyclerAdapter
:
private OnClick mListener;
Then remove static also from the definition of the ViewHolder
class so it becomes an inner class and can access the listener directly: 然后从
ViewHolder
类的定义中也删除static,使其成为一个内部类并可以直接访问侦听器:
public class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
After doing this you will still have to fix the RatedFragment
since it will show the same DetailsFragment
without the extra you are currently requiring. 完成此操作后,您仍将必须修复
RatedFragment
因为它将显示相同的DetailsFragment
而没有您当前需要的额外信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.