在我的应用程序中,我正在为具有多个视图的回收站视图实现自定义适配器。在适配器中,我列出了从主活动传入的对象列表,并在其中设置了视图和onClickListeners。对于我激发的一种意图,我正在编辑适配器中设置的内容。活动返回后-适配器不会更新。我不确定如何在活动完成后为适配器实现接口或onActivityForResult()方法以在RecyclerView中重新配置此视图。
我尝试实现一个接口,但是不确定如何在我在主要活动(片段)中声明适配器时准确地执行此操作,然后从那里添加对象列表。在适配器中,我根据添加的对象在其中设置视图。
这是我的主要片段类中的相关代码:
我正在向mObjects添加各种对象。
public class ProfileFragment extends Fragment{
public final static String TAG = "ProfileFragment"; // tag for logging from this activity
final ParseUser user = ParseUser.getCurrentUser();
// For post feed:
ArrayList<Object> mObjects;
ArrayList<Post> mPosts;
RecyclerView mLayout;
MultiViewAdapter mMultiAdapter;
// For stats view:
HashMap<String, Integer> mCities; // Contains the cities and number of times visited by user
HashMap<String, Integer> mCountries; // Contains the countries and number of times visited by user
HashMap<String, Integer> mContinents; // Contains the continents and number of times visited by user
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_profile, container, false);
setUpLogOutButton(v);
// Populate stat maps and get posts
mObjects = new ArrayList<>();
mCities = new HashMap<>();
mCountries = new HashMap<>();
mContinents = new HashMap<>();
mPosts = new ArrayList<>();
// Get posts
getPosts();
mObjects.add(user);
// For post feed view:
mMultiAdapter = new MultiViewAdapter(getActivity(), mObjects);
mLayout = v.findViewById(R.id.rvPosts);
mLayout.setLayoutManager(new LinearLayoutManager(getContext()));
mLayout.setAdapter(mMultiAdapter);
return v;
}
}
这是我的适配器中的相关代码:
public class MultiViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context mContext;
ArrayList<Object> items;
// Identifier for objects in items and which view to load:
private final int USER_INFO = 0, POST = 1, STAT = 2;
// The total number of cities, countries, and continents in the world:
public final int totalNumCities = 4416;
public final int totalNumCountries = 195;
public final int totalNumContinents = 7;
public MultiViewAdapter(Context context, ArrayList<Object> items) {
this.items = items;
this.mContext = context;
}
@Override
public int getItemCount() {
return items.size();
}
//Returns the view type of the item at position for the purposes of view recycling.
@Override
public int getItemViewType(int position) {
if (items.get(position) instanceof Post) {
return POST;
} else if (items.get(position) instanceof ParseUser) {
return USER_INFO;
} else if(items.get(position) instanceof HashMap){
return STAT;
}
return -1;
}
/**
* This method creates different RecyclerView.ViewHolder objects based on the item view type.
*
* @param viewGroup ViewGroup container for the item
* @param viewType type of view to be inflated
* @return viewHolder to be inflated
*/
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
switch (viewType) {
case POST:
View v1 = inflater.inflate(R.layout.item_post_card, viewGroup, false);
viewHolder = new PostViewHolder(v1);
break;
case USER_INFO:
View v2 = inflater.inflate(R.layout.item_user_information, viewGroup, false);
viewHolder = new UserInfoViewHolder(v2);
break;
case STAT:
View v3 = inflater.inflate(R.layout.item_user_stats, viewGroup, false);
viewHolder = new StatViewHolder(v3);
}
return viewHolder;
}
/**
* This method internally calls onBindViewHolder(ViewHolder, int) to update the
* RecyclerView.ViewHolder contents with the item at the given position
* and also sets up some private fields to be used by RecyclerView.
*
* @param viewHolder The type of RecyclerView.ViewHolder to populate
* @param position Item position in the viewgroup.
*/
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
switch (viewHolder.getItemViewType()) {
case POST:
PostViewHolder vh1 = (PostViewHolder) viewHolder;
configurePostViewHolder(vh1, position);
break;
case USER_INFO:
UserInfoViewHolder vh2 = (UserInfoViewHolder) viewHolder;
configureUserInfoViewHolder(vh2, position);
break;
case STAT:
StatViewHolder vh3 = (StatViewHolder) viewHolder;
configureStatViewHolder(vh3, position);
break;
}
}
private void configureStatViewHolder(final StatViewHolder vh3, final int position){
final HashMap<String, Integer> cities = (HashMap<String, Integer>) items.get(position);
if(cities!= null){
// For pie chart
// Cities:
// TODO: add pie chart for continents and countries and put this in seperate method
List<PieEntry> pieEntries = new ArrayList<>();
pieEntries.add(new PieEntry(cities.size(), "Visited Cities"));
pieEntries.add(new PieEntry(totalNumCities-cities.size(), "Unvisited Cities"));
PieDataSet pieDataSet = new PieDataSet(pieEntries, "City Stats");
pieDataSet.setColors(R.color.colorPrimary, R.color.colorPrimaryDark);
PieData pieData = new PieData(pieDataSet);
vh3.getmPieChart().setData(pieData);
vh3.getmPieChart().animateY(1000);
vh3.getmPieChart().invalidate();
}
}
private void configurePostViewHolder(final PostViewHolder vh1, final int position) {
final Post post = (Post) items.get(position);
if (post != null) {
vh1.getRootView().setTag(post);
String cityName = post.getCity();
String countryName = post.getCountry();
String continentName = post.getContinent();
vh1.getTvName().setText(cityName + ", " + countryName + ", " + continentName);
vh1.getTvName().setTextColor(Color.WHITE);
vh1.getvPalette().setBackgroundColor(ContextCompat.getColor(mContext, R.color.grey));
SimpleTarget<Bitmap> target = new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
vh1.getIvProfile().setImageBitmap(resource);
Palette p = Palette.from(resource).generate();
vh1.getvPalette().setBackgroundColor(ContextCompat.getColor(mContext, R.color.grey));
}
};
vh1.getIvProfile().setTag(target);
// TODO: Maybe don't crop image as it looks very small
if(post.getImage()!=null) {
Glide.with(mContext).asBitmap().load(post.getImage().getUrl()).centerCrop().into(target);
} else {
// TODO: fix default image loaded where no image present to be prettier
Glide.with(mContext).asBitmap().load(R.drawable.ic_add_photo).centerCrop().into(target);
}
vh1.getIvProfile().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent it = new Intent(mContext, EditPost.class);
Bundle bundle = new Bundle();
bundle.putSerializable(Post.class.getSimpleName(), post);
it.putExtras(bundle);
// Start activity for result to reconfigure user view after return
((Activity) mContext).startActivityForResult(it, 2121);
}
});
}
}
private void configureUserInfoViewHolder(UserInfoViewHolder vh2, final int position) {
ParseUser user = (ParseUser) items.get(position);
if (user != null) {
if (user.getParseFile("profileImg") != null) {
vh2.setmIvProfileImage(user.getParseFile("profileImg").getUrl(), mContext);
} else {
Glide.with(mContext).load(R.drawable.ic_user).into(vh2.getmIvProfileImage());
}
vh2.getmTvEditProfile().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent it = new Intent(mContext, UserSettings.class);
** SEE HERE FOR INTENT FIRED **
(mContext).startActivityForResult(it);
}
});
}
}
从那里开始我的UserSettings活动,用户可以在其中更改信息。
public class UserSettings extends AppCompatActivity {
ImageView mIvProfileImage;
TextView mTvEditPhoto;
ImageView mIvBackArrow;
ImageView mIvSave;
EditText mEtUsername;
EditText mEtNumber;
EditText mEtEmail;
public String photoFileName = "photo.jpg";
public static final int REQUEST_CODE = 101;
File mPhotoFile;
ParseFile mParseFile;
final ParseUser user = ParseUser.getCurrentUser();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_settings);
// mIntentListener = getCallingActivity()
// Set Views
mIvProfileImage = findViewById(R.id.ivProfileImageMain);
mTvEditPhoto = findViewById(R.id.tvEditPhoto);
mIvBackArrow = findViewById(R.id.ivBack);
mEtUsername = findViewById(R.id.etUsername);
mEtNumber = findViewById(R.id.etNumber);
mEtEmail = findViewById(R.id.etEmail);
mIvSave = findViewById(R.id.ivSave);
updateCurrentViews();
// Set on click listener for photo
mTvEditPhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(UserSettings.this);
builder.setTitle("Upload or Take a Photo");
builder.setPositiveButton("Upload", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Upload image
startActivityForResult(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI), Constants.GET_FROM_GALLERY);
}
});
builder.setNegativeButton("Take a Photo", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Take Photo
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
PhotoHelper photoHelper = new PhotoHelper();
mPhotoFile = photoHelper.getPhotoFileUri(UserSettings.this, photoFileName);
Uri fileProvider = FileProvider.getUriForFile(UserSettings.this, "com.example.fileprovider", mPhotoFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileProvider);
if (intent.resolveActivity(UserSettings.this.getPackageManager()) != null) {
startActivityForResult(intent, Constants.CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
});
// Go back to profile activity if user clicks back
mIvBackArrow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
mIvSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mParseFile != null) {
user.put("profileImg", mParseFile);
}
user.setEmail(mEtEmail.getText().toString());
user.setUsername(mEtUsername.getText().toString());
user.put("phone", mEtNumber.getText().toString());
user.put("email", mEtEmail.getText().toString());
setResult(RESULT_OK, new Intent());
user.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
updateCurrentViews();
finish();
}
});
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, final Intent data) {
if (requestCode == Constants.CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == this.RESULT_OK) {
Bitmap takenImage = BitmapFactory.decodeFile(mPhotoFile.getAbsolutePath());
mIvProfileImage.setImageBitmap(takenImage);
PhotoHelper photoHelper = new PhotoHelper();
File photoFile = photoHelper.getPhotoFileUri(this, photoFileName);
mParseFile = new ParseFile(photoFile);
} else {
mParseFile = null;
Toast.makeText(this, "Picture wasn't taken!", Toast.LENGTH_SHORT).show();
}
} else {
if (resultCode == this.RESULT_OK) {
Bitmap bitmap = null;
Uri selectedImage = data.getData();
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImage);
} catch (Exception e) {
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] image = stream.toByteArray();
mParseFile = new ParseFile("profpic.jpg", image);
final Bitmap finalBitmap = bitmap;
Glide.with(this).load(finalBitmap).into(mIvProfileImage);
} else {
mParseFile = null;
}
}
}
public void updateCurrentViews() {
// For profile image:
mIvProfileImage = findViewById(R.id.ivProfileImageMain);
if (user.getParseFile("profileImg") != null) {
Glide.with(this).load(user.getParseFile("profileImg").getUrl()).into(mIvProfileImage);
} else {
Glide.with(this).load(R.drawable.ic_user).into(mIvProfileImage);
}
// EditText:
mEtUsername.setText(user.getUsername());
mEtNumber.setText(String.format("%s", user.get("phone")));
mEtEmail.setText(String.format("%s", user.get("email")));
}
}
问题是当UserSettingsActivity完成更新的信息时,该信息未反映在适配器中,并且显示了旧信息。
编辑回应以回复评论
这是我的主要活动:
public class HomeActivity extends AppCompatActivity {
final FragmentManager fragmentManager = getSupportFragmentManager();
final Fragment fragment1 = new MapFragment();
final Fragment fragment2 = new DiscoverFragment();
final Fragment fragment3 = new ProfileFragment();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
BottomNavigationView navView = findViewById(R.id.nav_view);
navView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
Fragment fragment;
switch (menuItem.getItemId()) {
case R.id.navigation_home:
fragment = fragment1;
break;
case R.id.navigation_dashboard:
fragment = fragment2;
break;
case R.id.navigation_notifications:
default:
fragment = fragment3;
break;
}
fragmentManager.beginTransaction().replace(R.id.flContainer, fragment).commit();
return true;
}
});
navView.setSelectedItemId(R.id.navigation_home);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
}
在我的ProfileFragment中,我添加了:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == 2121){
// the user information is at item 0
mMultiAdapter.notifyItemChanged(0);
}
}
在适配器中,我从以下代码开始活动:
((Activity) mContext).startActivityForResult(it, 2121);
最佳答案
您需要在ProfileFragment中具有onActivityResult()函数,因为它将在UserSettings活动完成时被调用。从那里您可以得到意图,并获得更改的数据。您的ProfileFragment具有适配器的实例,因此您可以在更新对象后调用notifyItemChanged函数。