设定:
具有一个片段的活动,该片段通过按钮单击实例化。在片段中使用构造函数Bundle
。在Bundle
中设置了String (surname)
和ArrayList<String> (fornames)
。片段通过回调分离。
问题:
当片段被分离时,String (surname)
会按预期被破坏,但ArrayList
仍然存在。因此,当调用片段的新实例时,会出现以前的ArrayList
条目。回调不是问题。该行为也没有回调。
我已经在点surname = Black
处检查了变量(fornename = Joe
和Log.d
),点{@ 1}},FRAG_CONSTRUCTOR
中的getArguments()
方法(onCreate
)和片段回调(FRAG_ARGS_ONCREATE
)。
FRAG_CALLBACK
与surname Black
中显示的LogCat
不符,但forname Joe
仍然存在。
的活动:
public class MainActivity extends AppCompatActivity implements FragRecycler.FragRecyclerCallBackListener {
private Button button;
private String surname;
private ArrayList<String> fornames;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fornames = new ArrayList<String>();
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addFragmentWithTransition(R.id.container, FragRecycler.newInstance(surname, fornames), "FRAG_RECYCLER");
}
});
}
public void addFragmentWithTransition(int containerViewId, Fragment fragment, String fragmentTag) {
getSupportFragmentManager()
.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.add(containerViewId, fragment, fragmentTag)
.addToBackStack(fragmentTag)
.commit();
}
@Override
public void onFragRecyclerCallback() {
Log.d("FRAG_CALLBACK", "forname: " + fornames + " surname: " + surname);
getSupportFragmentManager().popBackStack();
}
@Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
}
片段:
public class FragRecycler extends Fragment {
private View v;
private Toolbar toolbar;
private TextInputEditText vSurname;
private RecyclerView rvForenames;
private AdapterForName adapter;
private FragRecyclerCallBackListener callback;
public interface FragRecyclerCallBackListener {
void onFragRecyclerCallback();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof AppCompatActivity){
try {
callback = (FragRecyclerCallBackListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement FragRecyclerCallBackListener");
}
}
}
@Override
public void onDetach() {
super.onDetach();
callback = null;
}
public static FragRecycler newInstance(String surname, ArrayList<String> fornames) {
Log.d("FRAG_CONSTRUCTOR", "forname: " + fornames + " surname: " + surname);
FragRecycler p = new FragRecycler();
Bundle b = new Bundle();
b.putString("SURNAME", surname);
b.putStringArrayList("FORNAMES", fornames);
p.setArguments(b);
return p;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("FRAG_ARGS_ONCREATE", "forname: " + getArguments().getStringArrayList("FORNAMES") + " surname: " + getArguments().getString("SURNAME"));
v = inflater.inflate(R.layout.frag_recycler, container, false);
toolbar = (Toolbar) v.findViewById(R.id.toolbar);
vSurname = (TextInputEditText) v.findViewById(R.id.surname);
rvForenames = (RecyclerView) v.findViewById(R.id.rv_forenames);
vSurname.setText(getArguments().getString("SURNAME"));
adapter = new AdapterForName("Forename", getArguments().getStringArrayList("FORNAMES"));
rvForenames.setAdapter(adapter);
rvForenames.setLayoutManager(new LinearLayoutManager(getContext()));
toolbar.setNavigationIcon(ContextCompat.getDrawable(getContext(), R.drawable.ic_clear));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
callback.onFragRecyclerCallback();
}
});
return v;
}
class AdapterForName extends RecyclerView.Adapter<AdapterForName.ViewHolder> {
private ArrayList<String> names;
private String callType;
public AdapterForName(String callType, ArrayList<String> names) {
this.callType = callType;
this.names = names;
if (names.size() == 0) {
addEmptyEntryToList();
} else {
if (!(names.get(names.size() - 1).trim().length() < 1)) {
addEmptyEntryToList();
}
}
}
protected void addEmptyEntryToList() {
names.add("");
notifyDataSetChanged();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.name, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
if (position == 0) {
holder.inputLayout.setHint(callType);
} else {
holder.inputLayout.setHint(String.valueOf(position + 1) + " th." + " " + callType);
}
holder.input.setText(names.get(position));
holder.input.setTag(position);
holder.input.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
final String inputText = s.toString().trim();
names.set(holder.getAdapterPosition(), inputText);
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
});
holder.input.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (!b) { // inputEditText hat keinen Focus mehr.
if (holder.input.getText().toString().trim().length() > 0){
int count = 0;
for (int i = 0; i < names.size(); i++) {
if (names.get(i).trim().length() == 0) {
count = count + 1;
}
}
if (count == 0) {
names.add("");
notifyDataSetChanged();
}
}
if (holder.input.getText().toString().trim().length() == 0){
int count = 0;
for (int i = 0; i < names.size(); i++) {
if (names.get(i).trim().length() == 0) {
count = count + 1;
}
}
if (count > 0) {
names.remove(holder.getAdapterPosition());
notifyDataSetChanged();
}
}
}
}
});
}
public ArrayList<String> getList() {
ArrayList<String> trimmedList = new ArrayList<>();
for (int i = 0; i < names.size(); i++) {
if (names.get(i).trim().length() > 0) {
trimmedList.add(names.get(i));
}
}
return trimmedList;
}
@Override
public int getItemCount() {
return names.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
public TextInputLayout inputLayout;
public TextInputEditText input;
public ViewHolder(View itemView) {
super(itemView);
inputLayout = (TextInputLayout) itemView.findViewById(R.id.input_layout);
input = (TextInputEditText) itemView.findViewById(R.id.input);
}
}
}
}
logcat的:
08-05 21:42:34.387 17055-17055/com.example.user.recyclertest W/art: Before Android 4.1, method int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
08-05 21:42:36.625 17055-17055/com.example.user.recyclertest D/FRAG_CONSTRUCTOR: forname: [] surname: null
08-05 21:42:36.643 17055-17055/com.example.user.recyclertest D/FRAG_ARGS_ONCREATE: forname: [] surname: null
08-05 21:42:41.852 17055-17055/com.example.user.recyclertest W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
08-05 21:42:41.857 17055-17055/com.example.user.recyclertest W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
08-05 21:42:45.200 17055-17055/com.example.user.recyclertest D/FRAG_CALLBACK: forname: [Joe] surname: null
08-05 21:42:45.486 17055-17055/com.example.user.recyclertest W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
08-05 21:42:45.487 17055-17055/com.example.user.recyclertest W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
08-05 21:43:03.441 17055-17055/com.example.user.recyclertest D/FRAG_CONSTRUCTOR: forname: [Joe, ] surname: null
答案 0 :(得分:0)
如果在FRAG_CALLBACK
来电中你引用了不同的字段,你期望得到什么?您引用了MainActivity.surname
和MainActivity.fornames
,但是在您的片段中,它们位于完全不同的内存位置,因为Bundle
中的值是按值传递的 - 当您调用putX
时然后getX
,你会得到一份副本。
答案 1 :(得分:0)
在您的活动的onCreate()
方法中,您可以编写
fornames = new ArrayList<String>();
将新的(空)ArrayList
实例分配给Activity的forenames
实例变量。然后你写
FragRecycler.newInstance(surname, fornames)
导致fornames
被添加到新的Fragment的“arguments”Bundle
b.putStringArrayList("FORNAMES", fornames);
最终传递给您的Adapter的构造函数
adapter = new AdapterForName("Forename", getArguments().getStringArrayList("FORNAMES"));
您的适配器将其分配给其names
实例变量:
this.names = names;
然后,当用户使用您的应用时,您的程序会继续修改适配器的names
列表。
这里要实现的关键是所有这些代码都在讨论相同的ArrayList
实例。因此,当您的应用添加名称或从适配器的names
列表中删除名称时,还在您的活动的fornames
列表中添加和删除名称。这是因为这两个变量指向同一个对象。
如果要确保Fragment无法修改Activity的fornames
列表实例,则应更改Fragment的newInstance()
方法,如下所示。替换此
b.putStringArrayList("FORNAMES", fornames);
用这个:
List<String> fornamesCopy = new ArrayList<>(fornames);
b.putStringArrayList("FORNAMES", fornamesCopy);
new
关键字表示现在您的Fragment与您的Activity有不同的 ArrayList实例,因此修改此实例不会影响另一个。这里使用的特定构造函数将确保这个新的ArrayList实例仍然保存与原始实例相同的值。