【问题标题】:Can not transfer an object by using Intent and Parcelable无法使用 Intent 和 Parcelable 传输对象
【发布时间】:2018-06-15 17:11:04
【问题描述】:

我正在使用 Firebase 制作新闻应用。当我尝试将对象转移到另一个活动时遇到问题。

一个例外:

"java.lang.RuntimeException: 无法启动活动 ComponentInfo{com.example.fx.fibi/com.example.fx.fibi.DetailActivity}: java.lang.NullPointerException: 尝试调用虚拟方法 'java.lang .String com.example.fx.fibi.News.getTitle()' 在空对象引用上。

这是我的代码:

主活动:

import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    private Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = (RecyclerView) findViewById(R.id.recycle_view);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        mRecyclerView.setAdapter(firebaseRecyclerAdapter);
    }

    Query query = FirebaseDatabase.getInstance().getReference().child("Global");

    FirebaseRecyclerOptions<News> options = new FirebaseRecyclerOptions.Builder<News>()
            .setQuery(query, News.class).build();

    final FirebaseRecyclerAdapter<News,NewsViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<News,
            NewsViewHolder>(options) {

        @NonNull
        @Override
        public NewsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.news_row, parent, false);

            return new NewsViewHolder(view);

        }

        @Override
        protected void onBindViewHolder(@NonNull NewsViewHolder holder, int position, @NonNull News model) {
            holder.setTitle(model.getTitle());
            holder.setDesc(model.getDesc());
            holder.setImage(getApplicationContext(), model.getImage());

            holder.setOnClickListener(new NewsViewHolder.ClickListener() {
                @Override
                public void onItemClick(View view, int position) {
                    Toast.makeText(MainActivity.this, "Item clicked at " + position, Toast.LENGTH_SHORT).show();
                    Intent intent = new Intent(MainActivity.this, DetailActivity.class);
                    intent.putExtra("news", position);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                }

                @Override
                public void onItemLongClick(View view, int position) {

                }
            });
        }
    };
    @Override
    protected void onStart() {
        super.onStart();
        firebaseRecyclerAdapter.startListening();

    }
}

DetailActivity(这个类在“title.setText(news.getTitle());”处得到 NullPointerException

public class DetailActivity extends AppCompatActivity {
    TextView title, desc;
    ImageView imageView;
    News news;
    String titleString, descString, image;
    Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        initCollapsingToolbar();

        imageView = findViewById(R.id.thumbnail_image_header);
        title = findViewById(R.id.detail_title);

        Intent intentThatStartedThisActivity = getIntent();
        if (intentThatStartedThisActivity.hasExtra("news")) {
            news = getIntent().getParcelableExtra("news");
            title.setText(news.getTitle());
            desc.setText(news.getDesc());
            Picasso.with(mContext).load(image).into(imageView);
        }
    }

    private void initCollapsingToolbar() {
        final CollapsingToolbarLayout collapsingToolbarLayout =
                (CollapsingToolbarLayout)findViewById(R.id.collapsing_toolbar);
        collapsingToolbarLayout.setTitle(" ");
        AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
        appBarLayout.setExpanded(true);

        appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            boolean isShow = false;
            int scrollRange = -1;

            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if (scrollRange == -1) {
                    scrollRange = appBarLayout.getTotalScrollRange();
                }
                if (scrollRange + verticalOffset == 0) {
                    collapsingToolbarLayout.setTitle(getString(R.string.app_name));
                    isShow = true;
                } else if (isShow) {
                    collapsingToolbarLayout.setTitle(" ");
                    isShow = false;
                }
            }
        });
    }
}

型号:

public class News implements Parcelable {
    private String title;
    private String desc;
    private String image;

    public News(String title, String desc, String image) {
        this.title = title;
        this.desc = desc;
        this.image = image;
    }

    public News (Parcel in) {
        String[] data = new String[3];
        in.readStringArray(data);
        title = data[0];
        desc = data[1];
        image = data[2];
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public News() {

    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeStringArray(new String[] {title, desc, image});
    }

    public static final Parcelable.Creator<News> CREATOR = new Parcelable.Creator<News>() {

        @Override
        public News createFromParcel(Parcel source) {
            return new News(source);
        }

        @Override
        public News[] newArray(int size) {
            return new News[size];
        }
    };
}

对不起,如果我的问题看起来很愚蠢,这是我的第一个完整应用程序。 谢谢!

我添加了一个对象列表List &lt;News&gt; newsList并将方法onItem click更改为:

if (position != RecyclerView.NO_POSITION) {
                        News clickedDataItem = newsList.get(position);
                        Toast.makeText(MainActivity.this, "Item clicked at " + position, Toast.LENGTH_SHORT).show();
                        Intent intent = new Intent(MainActivity.this, DetailActivity.class);
                        intent.putExtra("news", clickedDataItem);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);
                    }

但现在我得到“java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)' on an null object reference”

【问题讨论】:

    标签: java android firebase


    【解决方案1】:

    您可以在您的模型类中实现java Serializable interface,而不是实现Parcelable,如下所示

    public class News implements java.io.Serializable {
        private static final long serialVersionUID = 1L;
        private String title;
        private String desc;
        private String image;
    
        public News(String title, String desc, String image) {
            this.title = title;
            this.desc = desc;
            this.image = image;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getDesc() {
            return desc;
        }
    
        public void setDesc(String desc) {
            this.desc = desc;
        }
    
        public String getImage() {
            return image;
        }
    
        public void setImage(String image) {
            this.image = image;
        }
    
        public News() {
            //empty contructor neeeded
        }
        @Overide
        public String toString(){
            return super.toString();
        }
    }
    

    然后你可以像这样传递对象的意图

    News news = new News("title", "desc", "image");
    Intent intent = new Intent(StartActivity.this, TargetActivity.class);
    intent.putExtra("news", news);
    startActivity(intent);
    

    为了从 Intent 中获取对象,您需要将 New 类强制转换为 Intent 结果,如下所示。

    News news = (News)getIntent().getSerializableExtra("news");
    

    【讨论】:

      【解决方案2】:

      在您的 onBindViewHolder 中,您输入了错误的数据。

      intent.putExtra("news", position); // position is int
      

      哪个位置是一个int,把News对象放在那个位置。

      【讨论】:

      • 谢谢!我更改了源代码,但它仍然无法正常工作。请看这个
      • 你在哪里初始化newsList
      • 它是全局的,MainActivity。有关系吗?
      • 这很重要,似乎newsListFirebaseRecyclerAdapter 检索了,我没有看到你初始化newsList
      • 是的,我做错了。我初始化列表,但没有分配给当前值。但我不知道该怎么做。如何获取当前对象列表?
      【解决方案3】:

      您可以将值设置为意图 ....

      Intent i = new Intent(FirstScreen.this, SecondScreen.class);   
      String strName = "value";
      i.putExtra("STRING_I_NEED", strName);
      startActivity(i);
      

      您可以在第二个活动中检索值............

      String newString;
      if (savedInstanceState == null) {
      Bundle extras = getIntent().getExtras();
      if(extras == null) {
          newString= null;
      } else {
          newString= extras.getString("STRING_I_NEED");
      }
      } else {
      newString= (String) savedInstanceState.getSerializable("STRING_I_NEED");
      }
      

      【讨论】:

      • 它很酷,但这样我传输字符串而不是对象。我说的对吗?
      【解决方案4】:
      news = getIntent().getIntExtra("news");
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-13
        • 1970-01-01
        • 1970-01-01
        • 2011-11-15
        相关资源
        最近更新 更多