I am currently in trouble with my project.
I am trying to separate functions into different classes instead of putting all in Activity class.
So I think I need to pass "view" from SettingsActivity to ConfigPresenter, from ConfigPresenter to ConfigEventHandler.
but I don not know why it doesn't work at all.
can anyone help me to know what the problem is?
Appreciate all the time and sorry that I only come stackoverflow to get information.
I hope I become a professional someday and help people here. :)
I make errors bold below.
SettingsActivity.java
- configPresenter.optionClicked **(view)**
ConfigPresenter.java
- eh.checkOption **(view)**
ConfigEventHandler.java
- AlertDialog.Builder builder = new AlertDialog.Builder **(SettingsActivity.class)**
- LayoutInflater inflater = SettingsActivity.class.**getLayoutInflater()**
- TextView titleUrl = (TextView) **findViewById**(title);
- TextView optionUrl = (TextView) **findViewById**(option);
SettingsActivity.java
public class SettingsActivity extends AppCompatActivity implements ConfigPresenter.View {
private ConfigPresenter configPresenter;
private Context context = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
}
public void optionClicked(View view) {
configPresenter.optionClicked(view);
}
}
ConfigPresenter.java
public class ConfigPresenter {
private View view;
private ConfigEventHandler eh;
private ConfigFileHandler fh;
public ConfigPresenter(ConfigPresenter.View view) {
this.view = view;
eh = new ConfigEventHandler();
fh = new ConfigFileHandler();
}
public void optionClicked(View view) {
eh.checkOption(view);
Log.d("Config", "Presenter");
}
}
ConfigEventHandler.java
public class ConfigEventHandler {
public void checkOption(View view) {
if ( view.getId() == R.id.layout_url ) {
showDialog(R.id.title_url, R.id.option_url);
} else if ( view.getId() == R.id.layout_port ) {
showDialog(R.id.title_port, R.id.option_port);
} else {
showDialog(R.id.title_path, R.id.option_path);
}
}
public void showDialog(int title, int option) {
AlertDialog.Builder builder = new AlertDialog.Builder(SettingsActivity.class);
LayoutInflater inflater = SettingsActivity.class.getLayoutInflater();
View content = inflater.inflate(R.layout.dialog, null);
builder.setView(content);
TextView titleUrl = (TextView) findViewById(title);
TextView dialogTitle = (TextView) content.findViewById(R.id.dialog_title);
TextView optionUrl = (TextView) findViewById(option);
EditText dialogOption = (EditText) content.findViewById(R.id.dialog_option);
dialogTitle.setText(titleUrl.getText());
dialogOption.setText(optionUrl.getText());
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
// ok
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// cancel
}
})
.show();
}
}
First of all, your classes aren't logical, but a few fixes for your current setup.
public class SettingsActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setcontentview etc.
}
public void optionClicked(View view){
ConfigPresenter.optionClicked(view,getLayoutInflater(),this);
}
}
ConfigPresenter
public class ConfigPresenter {
public static void optionClicked(View view, LayoutInflater inflater, Context context){
ConfigEventHandler.checkOption(view,inflater,context);
}
}
ConfigEventHandler
public class ConfigEventHandler {
public static void checkOption(View view, LayoutInflater inflater, Context context){
showDialog(inflater,context);
}
private static void showDialog(LayoutInflater inflater, Context context){
AlertDialog dialog = new AlertDialog.Builder(context).create();
View content = inflater.inflate(R.layout.alert_add_item,null);
dialog.setContentView(content);
dialog.show();
}
}
In SettingsActivity:
private ConfigPresenter configPresenter;
private Context context = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
// Initialize configPresenter:
configPresenter = new ConfigPresenter(this)
}
And in the constructor method in ConfigPresenter, you can remove the weird ConfigPresenter.View like this:
public class ConfigPresenter {
private ConfigEventHandler eh;
private ConfigFileHandler fh;
private Context context;
public ConfigPresenter(Context context) {
this.context = context;
eh = new ConfigEventHandler(context);
fh = new ConfigFileHandler();
}
/* ... */
}
EDIT:The Context also needs to be passed down. Edited code above, and the edits below also needs to be added.
public class ConfigEventHandler {
private Context context;
// Constructor with Context
public ConfigEventHandler(Context context) {
this.context = context;
}
/* ... */
public void showDialog(int title, int option) {
// Passing the context to the Builder:
AlertDialog.Builder builder = new AlertDialog.Builder(context);
/* ... */
}
However - this approach seems to only cause a lot of headache. Why do you want to split up your code in so many classes?
Related
I'm currently working on an app in which users can create groups and add members to groups. Today I created a new user to test the app. When I logged in this new user I checked to see if it was a part of any groups, which I didn't expect it to be seeing as it was new. And it wasn't. But then when I logged in my usual user and clicked groups I saw the name of the test user. Why does it appear that this user is a part of a group it was never added to?
It should be noted that when looking through my firebase this test user doesn't appear to have been invited either. I'm using firestore recycler adapter to fetch data in a recyclerView.
Below is the code for my adapter responsible for adding members to a specific group.
FirestoreMemberAdapter.java:
public class FirestoreMemberAdapter extends FirestoreRecyclerAdapter<MemberModel, FirestoreMemberAdapter.MemberViewHolder> {
private static final String TAG = FirestoreMemberAdapter.class.getSimpleName();
private Context context;
private String projectId;
private String projectName;
public FirestoreMemberAdapter(#NonNull FirestoreRecyclerOptions<MemberModel> options, Context context, String projectId, String projectName) {
super(options);
this.context = context;
this.projectName = projectName;
this.projectId = projectId;
}
#Override
protected void onBindViewHolder(#NonNull MemberViewHolder holder, int position, #NonNull final MemberModel model) {
holder.mTextView.setText(model.getName());
if (model.getProfile_image() == null) {
Picasso.get().load(R.drawable.profile_image).into(holder.mImageview);
} else {
Picasso.get().load(model.getProfile_image()).into(holder.mImageview);
}
holder.mLinearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "onClick: Clicked on FirestoreMemberAdapter ");
Intent intent = new Intent(context, ProfileMemberPage.class);
intent.putExtra(StringCreator.PROJECT_TITLE, projectName);
intent.putExtra(StringCreator.PROJECT_ID, projectId);
intent.putExtra(StringCreator.NAME, model.getName());
intent.putExtra(StringCreator.EMAIL, model.getEmail());
intent.putExtra(StringCreator.USER_ID, model.getUser_id());
intent.putExtra(StringCreator.USER_INFORMATION, model.getUser_information());
context.startActivity(intent);
}
});
}
#NonNull
#Override
public MemberViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_projectmembers, parent, false);
return new MemberViewHolder(view);
}
public class MemberViewHolder extends RecyclerView.ViewHolder {
private LinearLayout mLinearLayout;
private TextView mTextView;
private ImageView mImageview;
public MemberViewHolder(#NonNull View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.memberTitle);
mLinearLayout = itemView.findViewById(R.id.layout_members);
mImageview = itemView.findViewById(R.id.memberImage);
}
}
}
Here is the activity in wihch the adapter is used.
projectClicked.java:
//widgets
private RecyclerView recyclerViewMembers;
private TextView projectName;
private Button cameraBtn;
private FloatingActionButton addUserBtn;
//Firebase
private FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
private Query query;
private FirestoreRecyclerOptions<MemberModel> options;
private FirestoreMemberAdapter adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_project_clicked);
projectName = findViewById(R.id.projectName);
addUserBtn = findViewById(R.id.addUserBtn);
cameraBtn = findViewById(R.id.cameraBtn);
initRecyclerView();
addUserBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent newIntent = new Intent(projectClicked.this, UserToProject.class);
Bundle projectBundle = getIntent().getExtras();
if (projectBundle != null) {
newIntent.putExtras(projectBundle);
}
startActivity(newIntent);
}
});
}
private void initRecyclerView() {
Log.d(TAG, "InitRecyclerView: init recyclerview");
if (getIntent().hasExtra(StringCreator.PROJECT_TITLE) && getIntent().hasExtra(StringCreator.PROJECT_ID)) {
final String pName = getIntent().getStringExtra(StringCreator.PROJECT_TITLE);
final String pID = getIntent().getStringExtra(StringCreator.PROJECT_ID);
projectName.setText(pName);
recyclerViewMembers = findViewById(R.id.recyclerView_members);
query = firebaseFirestore.collection("users");
options = new FirestoreRecyclerOptions.Builder<MemberModel>().setQuery(query, MemberModel.class).build();
adapter = new FirestoreMemberAdapter(options, projectClicked.this, pID, pName);
recyclerViewMembers.setHasFixedSize(true);
recyclerViewMembers.setAdapter(adapter);
recyclerViewMembers.setLayoutManager(new LinearLayoutManager(projectClicked.this));
}
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
Hope this makes sense, please reach out if it doesn't. Thank you in advance.
As #McSlinPlay mentioned, the reason could be pointed out to your code in projectClicked.java where you created your query and all the users (including the test user) are part of this collection:
query = firebaseFirestore.collection("users");
I have a little question for you. I have an app which displays a list of subjects which could be removed or addedd. During developing I realized that I could add new subject without call notifyDataSetChange, why?
Class (ListSubject) which manage list of subjects:
public static ListView mListView;
private Context mContext;
List<Subject> data;
SubjectAdapter subjectSubjectAdapter;
public ListSubject(Context mContext) {
this.mContext = mContext;
}
public List<Subject> populateList() {
DBManager db = new DBManager(mContext);
data = db.GetSubjects();
return data;
}
public void DeleteAll(){
DBManager db = new DBManager(mContext);
db.ClearTable("TBLSUBJECTS");
data.clear();
}
public void AddSubject(String name, int frequency){
DBManager db = new DBManager(mContext);
Subject subToAdd = db.InsertSubject(name, frequency);
data.add(subToAdd);
}
public void DeleteSubject(int id){
DBManager db = new DBManager(mContext);
db.DeleteSubject(id);
}
}
Class (ListSubjectActivity) which rappresents the activity where is listview:
DBManager db;
Button btnClearSubjectTable;
Button btnAddSub;
Context mContext;
private List<Subject> mListSubject;
private SubjectAdapter subjectAdapter;
private ListView lvSubject;
private ListSubject ls;
public ListSubjectActivity(Context mContext) {
this.mContext = mContext;
}
public ListSubjectActivity(){}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_subject);
db = new DBManager(this);
btnClearSubjectTable = (Button) findViewById(R.id.btnClearSubjectTable);
btnAddSub = (Button) findViewById(R.id.btnAddSubject);
lvSubject = (ListView)findViewById(R.id.subjectList);
mListSubject = new ArrayList<>();
ls = new ListSubject(getApplicationContext());
mListSubject = ls.populateList();
btnClearSubjectTable.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ls.DeleteAll();
subjectAdapter.notifyDataSetChanged();
}
});
btnAddSub.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Dialog dialog = new Dialog(ListSubjectActivity.this);
dialog.setContentView(R.layout.dialog_insert_subject);
final EditText txtNewSubName = (EditText) dialog.findViewById(R.id.txtNewSubName);
final EditText txtFreqNewSub = (EditText) dialog.findViewById(R.id.txtFreqNewSub);
Button dialogButtonOK = (Button) dialog.findViewById(R.id.btnOK);
dialogButtonOK.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AddSubject(txtNewSubName.getText().toString(), Integer.parseInt(txtFreqNewSub.getText().toString()));
subjectAdapter.notifyDataSetChanged();
dialog.dismiss();
}
});
Button dialogButtonCancel = (Button) dialog.findViewById(R.id.btnCancel);
dialogButtonCancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
Window window = dialog.getWindow();
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, 700);
}
});
subjectAdapter = new SubjectAdapter(getApplicationContext(), mListSubject);
lvSubject.setAdapter(subjectAdapter);
}
public void AddSubject(String newSub, int frequency)
{
ls.AddSubject(newSub, frequency);
}
My subject adapter:
private Context mContext;
private List<Subject> mList;
private ListSubject ls;
public SubjectAdapter(Context mContext, List<Subject> mList) {
this.mContext = mContext;
this.mList = mList;
}
#Override
public int getCount() {
return mList.size();
}
#Override
public Object getItem(int position) {
return mList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = View.inflate(mContext, R.layout.item_subject_list,null);
TextView txtSubjectName = v.findViewById(R.id.txtName);
TextView txtFrequency = v.findViewById(R.id.txtFrequency);
txtSubjectName.setText(mList.get(position).GetSubjectName());
txtFrequency.setText(Integer.toString(mList.get(position).GetFrequency()));
ls = new ListSubject(mContext);
ImageButton btnDeleteSub = (ImageButton) v.findViewById(R.id.btnDeleteSub);
btnDeleteSub.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ls.DeleteSubject(mList.get(position).GetSubjectID());
mList.remove(position);
notifyDataSetChanged(); useless
}
});
return v;
}
}
Keep in mind please, that I'm new in android development so could be make a lot of mistake. Thank you who help me
If your current code is what you're wondering about, you are calling notifyDataSetChanged() when adding an item. It's right here:
Button dialogButtonOK = (Button) dialog.findViewById(R.id.btnOK);
dialogButtonOK.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AddSubject(txtNewSubName.getText().toString(), Integer.parseInt(txtFreqNewSub.getText().toString()));
subjectAdapter.notifyDataSetChanged(); //see?
dialog.dismiss();
}
});
My app crashes every time the Splash Screen has slept for 5 seconds and it just won't start my slider.I'd like to add by saying that I've tried using Shared Preferences but the error tends to persist.Any help would be appreciated.The method launchmain2() is basically nothing but calling a blank activity named Main2Activity.I haven't created as many layouts for the slider as I would need but rather just one which gets all its resources accordingly from the Slider class.Here's the full code
MainActivity
public class MainActivity extends AppCompatActivity {
ImageView iv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = findViewById(R.id.welcome_image);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.transition);
iv.setAnimation(animation);
Thread loading = new Thread() {
public void run() {
try {
sleep(5000);
Intent main = new Intent(getApplicationContext(),Slide_Adapter.class);
startActivity(main);
finish();
}
catch (Exception e) {
e.printStackTrace();
}
}
};
loading.start();
}
}
Slide_Adapter
public class Slide_Adapter extends AppCompatActivity {
ViewPager pager;
Slider adapter;
Preferences preferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slide__adapter);
pager = findViewById(R.id.viewpager);
adapter = new Slider(this);
pager.setAdapter(adapter);
preferences = new Preferences(this);
if(!preferences.First()){
launchmain2();
finish();
}
}
private void launchmain2() {
preferences.FirstTime(false);
Intent intent = new Intent(Slide_Adapter.this, Main2Activity.class);
startActivity(intent);
finish();
}
}
Slider
public class Slider extends PagerAdapter {
private Context context;
public Slider(Slide_Adapter slide_adapter) {
this.context = context;
}
public int images[] = {R.drawable.add, R.drawable.call, R.drawable.message};
public String title[] = {"ADD A CONTACT", "MAKE CALLS", "TEXT"};
public int background[] = {
Color.rgb(255,0,0),
Color.rgb(128,255,0),
Color.rgb(255,0,255)};
#Override
public int getCount() {
return title.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return (view == (RelativeLayout)object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.slides, container, false);
RelativeLayout relativeLayout = view.findViewById(R.id.relative_layout);
ImageView imageView = view.findViewById(R.id.image);
TextView textView = view.findViewById(R.id.description);
relativeLayout.setBackgroundColor(background[position]);
imageView.setImageResource(images[position]);
textView.setText(title[position]);
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((RelativeLayout)object);
}
}
Preference Class
public class Preferences {
SharedPreferences sharedPreferences;
SharedPreferences.Editor editor;
Context context;
private static final String FIRST_LAUNCH = "A";
int MODE = 0;
private static final String PREFERENCE = "B";
public Preferences(Context context) {
this.context = context;
sharedPreferences = context.getSharedPreferences(PREFERENCE, MODE);
editor = sharedPreferences.edit();
}
public void FirstTime(boolean first){
editor.putBoolean(FIRST_LAUNCH, first);
editor.commit();
}
public boolean First(){
return sharedPreferences.getBoolean(FIRST_LAUNCH, true);
}
}
This issue arises because of the null context. Update context on Slider Adapter page.
Context update
private Context mContext;
public Slider(Context context) {
this.mContext = context;
}
And then use the mContext for instantiating the item.
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Update: For opening another activity for second time opening, change your MainActivity like this.
public class MainActivity extends AppCompatActivity {
ImageView iv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Preferences.init(getApplicationContext());// Also add this
iv = findViewById(R.id.welcome_image);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.transition);
iv.setAnimation(animation);
Thread loading = new Thread() {
public void run() {
try {
sleep(5000);
if(Preferences.getIsFirst() == false){
Preferences.writeFirstTimeOpen(true);
Intent main = new Intent(getApplicationContext(),Slide_Adapter.class);
startActivity(main);
finish();
}else{
Intent main = new Intent(getApplicationContext(), Main2Activity.class);
startActivity(main);
finish();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
};
loading.start();
}
}
And Preference Class:
public class Preferences {
private static SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;
Context context;
private static final String FIRST_LAUNCH = "A";
int MODE = 0;
private static final String PREFERENCE = "B";
public static void init(Context context) {
if (sharedPreferences == null) {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
}
}
public static boolean writeFirstTimeOpen(boolean value) {
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(FIRST_LAUNCH, value);
return editor.commit();
}
public boolean getIsFirst(){
return sharedPreferences.getBoolean(FIRST_LAUNCH, true);
}
}
Please check this, as this will also fix another first time opening issue.
You need to modify like this your constructor
public Slider(Context context) {//Add Context in parameter
this.context = context;
}
And please go though this link how to set and get value from shared-preferences
Hope this helps you
I noticed that parameter in constructor of Slider class not define as needed
What you do
public Slider(Slide_Adapter slide_adapter) {//There is not Context in parameter
this.context = context;//context will be still null
}
What need to do
public Slider(Context context) {//Add Context in parameter
this.context = context;
}
Here I'm trying to make a quiz application without using databases (requirement). Each question has 4 options.
I had made a class for Questions. Now, in the activity in which I want to show my data, I'm unable to get method to fetch the data from the QuestionModelClass.
I had made 2D Array but it gets more complicated to get it. Is there any way to bind 3 of the classes (QuestionModelClass, Adapter class, and Activity class)?
public class QuestionsModelClass {
private String sQuestion;
private String sRightAnswer;
private List<String> sOptions;
QuestionsModelClass(){
sQuestion = null;
sRightAnswer = null;
sOptions = null;
}
public QuestionsModelClass(String sQuestion, String sRightAnswer, List<String> sOptions) {
this.sQuestion = sQuestion;
this.sRightAnswer = sRightAnswer;
this.sOptions = sOptions;
}
public String getsQuestion() {
return sQuestion;
}
public void setsQuestion(String sQuestion) {
this.sQuestion = sQuestion;
}
public String getsRightAnswer() {
return sRightAnswer;
}
public void setsRightAnswer(String sRightAnswer) {
this.sRightAnswer = sRightAnswer;
}
public List<String> getsOptions() {
return sOptions;
}
public void setsOptions(List<String> sOptions) {
this.sOptions = sOptions;
}
}
And my Adapter Class
public class QuizAdapter extends BaseAdapter {
private Context context;
private List<QuestionsModelClass> questionClassList;
private String[][] options;
private LayoutInflater inflater;
private QuizAdapter(Context c, List<QuestionsModelClass> l){
this.context= c;
this.questionClassList = l;
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return questionClassList.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.questionpattern, parent,false);
QuestionsModelClass questions = questionClassList.get(position);
TextView quesText= convertView.findViewById(R.id.questionTextView);
RadioButton radioButtonA = convertView.findViewById(R.id.optionA);
RadioButton radioButtonB = convertView.findViewById(R.id.optionB);
RadioButton radioButtonC = convertView.findViewById(R.id.optionC);
RadioButton radioButtonD = convertView.findViewById(R.id.optionD);
return convertView;
}
And this is the Activity class in which I am trying to implement all the functions
public class QuizActivity extends Activity {
final Context context= this;
private List<QuestionsModelClass> classObject;
Button okayButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
String[] question= new String[]{"Q1. ABDE", "Q2. ADDASD"};
String[][] op;
String[] right = new String[]{"abc","def"};
classObject = new ArrayList<>();
op= new String[][]{
{"a1", "2", "3", "4"},
{"b1","b2","b3","b4"}};
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.customdialoguebox);
dialog.show();
okayButton = (Button) dialog.findViewById(R.id.okayButton);
okayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(QuizActivity.this,"Good Luck!", Toast.LENGTH_SHORT).show();
dialog.cancel();
}
});
}
I'm creating a chat feature for an application and it works super fine. But I would like to show the user that message has been sent or it still wating for the server's response.
Fields:
List<ChatMessage> chatMessages;
ChatAdapter chatAdapter;
RecyclerView chatRecyclerView;
ImageButton submitMessageBtn;
this how I send a message on my ChatActivity class:
public void submitMessage(final String messageType, final byte[] message){
final ChatMessageResponse messageObject = new ChatMessageResponse();
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
messageObject.setMessage( message);
messageObject.setYours(true);
messageObject.setUserNickname(getNickname());
messageObject.setCreationDate(DateTime.now().withZone(DateTimeZone.UTC));
messageObject.setType(messageType);
AddMessage(messageObject);
}
#Override
protected Void doInBackground(Void... voids) {
try {
chatClient.chat().sendMessage(eventId, messageType, message);
runOnUiThread(new Runnable() {
#Override
public void run() {
// Update message on the list after has been sent to server
}
});
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
public void AddMessage(ChatMessage message)
{
chatMessages.add(message);
chatAdapter.notifyDataSetChanged();
chatRecyclerView.scrollToPosition(chatMessages.size() -1);
}
When message is immediatly added to the adapter it should look like this:
my ChatAdapter class is setup like this:
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ChatViewHolder> {
private static final int VIEW_TYPE_MESSAGE_THIS_USER = 0;
private static final int VIEW_TYPE_MESSAGE_OTHER_USER = 1;
private final Activity activity;
public List<ChatMessage> chats=new ArrayList<>();
ArrayList<String> usercolor=new ArrayList<>();
Context mContext;
View view;
public ChatAdapter(List<ChatMessage> chats, Context mContext, Activity activity) {
this.chats = chats;
this.mContext = mContext;
this.activity = activity;
}
#Override
public ChatViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
mContext = parent.getContext();
if (viewType == VIEW_TYPE_MESSAGE_OTHER_USER) {
view = View.inflate(mContext, R.layout.message_item_left, null);
} else if (viewType == VIEW_TYPE_MESSAGE_THIS_USER){
view = View.inflate(mContext, R.layout.message_item, null);
}
return new ChatViewHolder(view,(View.OnLongClickListener)activity);
}
#Override
public void onBindViewHolder(final ChatViewHolder holder, int position){
final ChatMessageResponse m = (ChatMessageResponse) chats.get(position);
if (getItemViewType(position) == VIEW_TYPE_MESSAGE_OTHER_USER){
holder.bindToView1(m);
} else if (getItemViewType(position) == VIEW_TYPE_MESSAGE_THIS_USER)
{
holder.bindToView(m);
}
}
#Override
public int getItemCount() {
return chats.size();
}
#Override
public int getItemViewType(int position) {
return chats.get(position).isYours() ? VIEW_TYPE_MESSAGE_THIS_USER : VIEW_TYPE_MESSAGE_OTHER_USER;
}
}
When the server's response is positive the views in the ChatViewHolder (that I don't show the code because is too long) should change visibility state
Someone told me to get a referece for the view and change it on the activity's asynctask or create a Callback listener for my adapter.
But I have no Idea how to do either one of then any help is appreciated.
Are you familiar with the use of "Callbacks" or "Interfaces"? You can create an interface and implement it in your activity. Pass the callback by parameters in the "AsyncTask" and use it there.
//Interface class
/**
* Created by gmora
*/
public interface IProcess {
void updateAdapter(String result);
}
On Activity:
public class YourActivity extends AppCompatActivity {
private IProcess mProcess;
private Adapter mRecyclerAdapter;
private RecyclerView mRecyclerView;
private List<ChatMessage> chats; //update chats on activity and refresh your adapter
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mProcess = new IProceso() {
#Override
public void updateAdapter(String pException) {
//update chats ... and update mAdater.notifyDataChange()...
// or mRecyclerView.setAdapter(new Adpater.... with new list chats)..
}
};
mRecyclerView = find....
// etc....
mRecyclerAdapter = new RecyclerAdapter( chats, ...);
mRecyclerView.setAdapter(mRecyclerAdapter);
}
}
Finally on AsyncTask... create a external class from AsyncTask please!
/**
* Created by gmora.
*/
public class YourAsyncTaskClass extends AsyncTask<String, Void, String > {
private IProcess iProcess;
public StarSearchPrinterTask(IProcess pIProcess) {
this.iProcess= pIProcess;
}
#Override
protected void onPreExecute() {
//loading... its optional
}
#Override
protected String doInBackground(String... interfaceType) {
// execute webservice or api and get results..
return results;
}
#Override
protected void onPostExecute(String results) {
mIProceso.updateAdapter(results);
}
}