Fragment TextView 无法从 parcelable 对象更新
Fragment TextView is not able to be updated from parcelable object
在我的片段中,我有一个要设置为特定字符串的 textView。我想从一个对象中获取 textView 的字符串,我将其作为可打包的发送到片段。
我可以检索 parcelable 对象并使用该对象获取字符串(当我记录它时,会显示正确的字符串)。但是当我想用它来设置textView时,textView并没有改变。
知道为什么会发生这种情况以及如何解决它吗?
谢谢!
Edit1: 我添加了 activity 片段所在的位置,也许错误在这里?
Edit2:我添加了数据 class(可打包对象)。但是删除了构造函数的内容只是为了便于阅读。
public class NavigationFragment extends Fragment {
private static final String TAG = "NavigationFragment";
public NavigationFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_navigation, container, false);
return view;
}
@Override
public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Bundle bundle = this.getArguments();
if(bundle!=null) {
Data data = (Data) bundle.getParcelable("data");
TextView stopTitle = (TextView) view.findViewById(R.id.stopTitle);
final String name = data.getTourName();
Log.d(TAG, name);
stopTitle.setText(name);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
tools:context=".DoTourActivity">
<TextView
android:id="@+id/stopTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:text="stopTitle"
android:textSize="30dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView"
android:layout_width="365dp"
android:layout_height="158dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.492"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/stopTitle"
tools:src="@drawable/placeholder_pic" />
<TextView
android:id="@+id/stopDescription"
android:layout_width="384dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="24dp"
android:text="stopDescriptionstopDescriptionstopDescription stopDescription stopDescription stopDescription stopDescription stopDescription stopDescription stopDescription stopDescriptionstopDescriptionstopDescription stopDescription stopDescription stopDescription stopDescription stopDescription stopDescription stopDescription"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="395dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/stopDescription">
<ImageView
android:id="@+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_menu_mylocation" />
<TextView
android:id="@+id/locationAdress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="locationAdress"
android:textSize="23dp" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_dialog_map" />
</LinearLayout>
<EditText
android:id="@+id/pincode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:ems="10"
android:inputType="number"
android:text="pincode"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout" />
<Button
android:id="@+id/confirmButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="confirm"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/pincode" />
</android.support.constraint.ConstraintLayout>
public class DoTourActivity extends AppCompatActivity {
private static final String TAG = "DoTourActivity";
private SectionStatePagerAdapter sectionStatePagerAdapter;
private ViewPager viewPager;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_do_tour);
//Fragment management
sectionStatePagerAdapter = new SectionStatePagerAdapter(getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.container);
setupViewPager(viewPager);
//Setup actionbar
Toolbar myToolbar = (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(myToolbar);
//get chosen location & build tour
Fragment fragment = new NavigationFragment();
String location = getIntent().getStringExtra("location");
Bundle bundle = new Bundle();
Data data = new Data(location);
bundle.putParcelable("data", data);
fragment.setArguments(bundle);
//launch fragment
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.container, fragment);
transaction.commit();
}
public void setupViewPager (ViewPager viewPager) {
SectionStatePagerAdapter adapter = new SectionStatePagerAdapter(getSupportFragmentManager());
adapter.addFragment(new NavigationFragment(), "navFragment");
adapter.addFragment(new QuestionFragment(), "qesFragment");
viewPager.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// switch(item.getItemId())
return super.onOptionsItemSelected(item);
}
}
public class Data implements Parcelable {
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Data createFromParcel(Parcel in) {
return new Data(in);
}
public Data[] newArray(int size) {
return new Data[size];
}
};
private String tourName;
int tourID;
int possiblePoints;
int stops;
Spot[] spots;
//while playing tour
int points = 0;
// Constructor
public Data(String tour){
}
public String getTourName() {
return tourName;
}
public void setTourName(String tourName) {
this.tourName = tourName;
}
public int getTourID() {
return tourID;
}
public void setTourID(int tourID) {
this.tourID = tourID;
}
public int getPossiblePoints() {
return possiblePoints;
}
public void setPossiblePoints(int possiblePoints) {
this.possiblePoints = possiblePoints;
}
public int getStops() {
return stops;
}
public void setStops(int stops) {
this.stops = stops;
}
public Spot[] getSpots() {
return spots;
}
public void setSpots(Spot[] spots) {
this.spots = spots;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
// Parcelling part
public Data(Parcel in){
this.tourName = in.readString();
this.tourID = in.readInt();
this.possiblePoints = in.readInt();
this.stops = in.readInt();
this.spots = in.createTypedArray(Spot.CREATOR);
this.points = in.readInt();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.tourName);
dest.writeInt(this.tourID);
dest.writeInt(this.possiblePoints);
dest.writeInt(this.stops);
for(Spot s : spots){
dest.writeParcelable(s, flags);
}
dest.writeInt(this.points);
}
}
感谢@Mike M。这已经解决了。
问题出在托管片段的 activity 上。在那里,我创建了两个不同的 NavigationFragments,并将其添加到 activity。 TextView 的更新发生在错误的那个上。
我从另一个答案中看到片段实例存在问题,但我相信您的 Parcelable
实施也存在问题。
public Data(Parcel in){
...
this.spots = in.createTypedArray(Spot.CREATOR);
...
}
@Override
public void writeToParcel(Parcel dest, int flags) {
...
for(Spot s : spots){
dest.writeParcelable(s, flags);
}
...
}
这两个调用需要镜像,目前不需要。与其自己遍历数组,不如使用 writeTypedArray()
方法:
public Data(Parcel in){
...
this.spots = in.createTypedArray(Spot.CREATOR);
...
}
@Override
public void writeToParcel(Parcel dest, int flags) {
...
dest.writeTypedArray(spots, flags);
...
}
如果您查看 writeTypedArray()
和 createTypedArray()
的实现,您会发现部分工作是编写一个指示数组大小的标志,以便代码知道在另一边读出多少实例。您的实施不包括此步骤,因此两者不兼容。
在我的片段中,我有一个要设置为特定字符串的 textView。我想从一个对象中获取 textView 的字符串,我将其作为可打包的发送到片段。 我可以检索 parcelable 对象并使用该对象获取字符串(当我记录它时,会显示正确的字符串)。但是当我想用它来设置textView时,textView并没有改变。
知道为什么会发生这种情况以及如何解决它吗?
谢谢!
Edit1: 我添加了 activity 片段所在的位置,也许错误在这里?
Edit2:我添加了数据 class(可打包对象)。但是删除了构造函数的内容只是为了便于阅读。
public class NavigationFragment extends Fragment {
private static final String TAG = "NavigationFragment";
public NavigationFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_navigation, container, false);
return view;
}
@Override
public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Bundle bundle = this.getArguments();
if(bundle!=null) {
Data data = (Data) bundle.getParcelable("data");
TextView stopTitle = (TextView) view.findViewById(R.id.stopTitle);
final String name = data.getTourName();
Log.d(TAG, name);
stopTitle.setText(name);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
tools:context=".DoTourActivity">
<TextView
android:id="@+id/stopTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:text="stopTitle"
android:textSize="30dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView"
android:layout_width="365dp"
android:layout_height="158dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.492"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/stopTitle"
tools:src="@drawable/placeholder_pic" />
<TextView
android:id="@+id/stopDescription"
android:layout_width="384dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="24dp"
android:text="stopDescriptionstopDescriptionstopDescription stopDescription stopDescription stopDescription stopDescription stopDescription stopDescription stopDescription stopDescriptionstopDescriptionstopDescription stopDescription stopDescription stopDescription stopDescription stopDescription stopDescription stopDescription"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="395dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/stopDescription">
<ImageView
android:id="@+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_menu_mylocation" />
<TextView
android:id="@+id/locationAdress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="locationAdress"
android:textSize="23dp" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_dialog_map" />
</LinearLayout>
<EditText
android:id="@+id/pincode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:ems="10"
android:inputType="number"
android:text="pincode"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout" />
<Button
android:id="@+id/confirmButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="confirm"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/pincode" />
</android.support.constraint.ConstraintLayout>
public class DoTourActivity extends AppCompatActivity {
private static final String TAG = "DoTourActivity";
private SectionStatePagerAdapter sectionStatePagerAdapter;
private ViewPager viewPager;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_do_tour);
//Fragment management
sectionStatePagerAdapter = new SectionStatePagerAdapter(getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.container);
setupViewPager(viewPager);
//Setup actionbar
Toolbar myToolbar = (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(myToolbar);
//get chosen location & build tour
Fragment fragment = new NavigationFragment();
String location = getIntent().getStringExtra("location");
Bundle bundle = new Bundle();
Data data = new Data(location);
bundle.putParcelable("data", data);
fragment.setArguments(bundle);
//launch fragment
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.container, fragment);
transaction.commit();
}
public void setupViewPager (ViewPager viewPager) {
SectionStatePagerAdapter adapter = new SectionStatePagerAdapter(getSupportFragmentManager());
adapter.addFragment(new NavigationFragment(), "navFragment");
adapter.addFragment(new QuestionFragment(), "qesFragment");
viewPager.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// switch(item.getItemId())
return super.onOptionsItemSelected(item);
}
}
public class Data implements Parcelable {
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Data createFromParcel(Parcel in) {
return new Data(in);
}
public Data[] newArray(int size) {
return new Data[size];
}
};
private String tourName;
int tourID;
int possiblePoints;
int stops;
Spot[] spots;
//while playing tour
int points = 0;
// Constructor
public Data(String tour){
}
public String getTourName() {
return tourName;
}
public void setTourName(String tourName) {
this.tourName = tourName;
}
public int getTourID() {
return tourID;
}
public void setTourID(int tourID) {
this.tourID = tourID;
}
public int getPossiblePoints() {
return possiblePoints;
}
public void setPossiblePoints(int possiblePoints) {
this.possiblePoints = possiblePoints;
}
public int getStops() {
return stops;
}
public void setStops(int stops) {
this.stops = stops;
}
public Spot[] getSpots() {
return spots;
}
public void setSpots(Spot[] spots) {
this.spots = spots;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
// Parcelling part
public Data(Parcel in){
this.tourName = in.readString();
this.tourID = in.readInt();
this.possiblePoints = in.readInt();
this.stops = in.readInt();
this.spots = in.createTypedArray(Spot.CREATOR);
this.points = in.readInt();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.tourName);
dest.writeInt(this.tourID);
dest.writeInt(this.possiblePoints);
dest.writeInt(this.stops);
for(Spot s : spots){
dest.writeParcelable(s, flags);
}
dest.writeInt(this.points);
}
}
感谢@Mike M。这已经解决了。
问题出在托管片段的 activity 上。在那里,我创建了两个不同的 NavigationFragments,并将其添加到 activity。 TextView 的更新发生在错误的那个上。
我从另一个答案中看到片段实例存在问题,但我相信您的 Parcelable
实施也存在问题。
public Data(Parcel in){ ... this.spots = in.createTypedArray(Spot.CREATOR); ... } @Override public void writeToParcel(Parcel dest, int flags) { ... for(Spot s : spots){ dest.writeParcelable(s, flags); } ... }
这两个调用需要镜像,目前不需要。与其自己遍历数组,不如使用 writeTypedArray()
方法:
public Data(Parcel in){
...
this.spots = in.createTypedArray(Spot.CREATOR);
...
}
@Override
public void writeToParcel(Parcel dest, int flags) {
...
dest.writeTypedArray(spots, flags);
...
}
如果您查看 writeTypedArray()
和 createTypedArray()
的实现,您会发现部分工作是编写一个指示数组大小的标志,以便代码知道在另一边读出多少实例。您的实施不包括此步骤,因此两者不兼容。