I am having an issue in setting up my Chronometer. The Java file shows an error at "updateTimerText" stating Cannot resolve method "updateTimerText (java.lang.string) How do I solve this? Everything is Fine on the fragment I am trying to cast this task to it is just the Chronometer.java file. If you need any other information or code, let me know. Thanks in advance.
package com.example.platinumirish.runassistwithdrawer;
import android.content.Context;
import runassist.demo.fragments.MainFragment;
/**
* Created by Platinum Irish on 22/06/2016.
*/
public class Chronometer implements Runnable {
public static final long MILLIS_TO_MINUTES = 60000;
public static final long MILLIS_TO_HOURS = 3600000;
private Context mContext;
private long mStartTime;
private boolean mIsRunning;
public Chronometer(Context context){
mContext = context;
}
public void start() {
mStartTime = System.currentTimeMillis();
mIsRunning = true;
}
public void stop() {
mIsRunning = false;
}
#Override
public void run() {
while(mIsRunning) {
long since = System.currentTimeMillis() - mStartTime;
int seconds = (int) (since / 1000 % 60);
int minutes = (int)(((since / MILLIS_TO_MINUTES)) % 60);
int hours = (int)((since / (MILLIS_TO_HOURS)) % 24);
int millis = (int) since % 1000;
MainFragment mainFragment = (MainFragment) mContext.updateTimerText(String.format(
"%02d;%02d;%02d;%03d", hours, minutes, seconds, millis
));
}
}
}
Here is my Main Fragment too if it will help in any way, shape or form.
package runassist.demo.fragments;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.TextView;
import com.example.platinumirish.runassistwithdrawer.R;
public class MainFragment extends Fragment{
private TextView mTvTime;
private Button mBtnStart;
private Button mBtnStop;
private Context mContext;
private Chronometer mChronometer;
private Thread mThreadChrono;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
mTvTime = (TextView) rootView.findViewById(R.id.chronometer);
mBtnStart = (Button) rootView.findViewById(R.id.start_button);
mBtnStop = (Button) rootView.findViewById(R.id.stop_button);
mBtnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mChronometer == null) {
mChronometer = new Chronometer(mContext);
mThreadChrono = new Thread((Runnable) mChronometer);
mThreadChrono.start();
mChronometer.start();
}
}
});
mBtnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mChronometer !=null) {
mChronometer.stop();
mThreadChrono.interrupt();
mThreadChrono = null;
mChronometer = null;
}
}
});
return rootView;
}
public void updateTimerText(final String time) {
runOnUiThread(new Runnable() {
#Override
public void run () {
mTvTime.setText(time);
}
});
}
private void runOnUiThread(Runnable runnable) {
}
}
((MainFragment) mContext).updateTimerText(...) this is the way you want to call it. Check the squares around mContext.
Also, your method updateTimerText returns void so this line:
MainFragment mainFragment = (MainFragment) mContext.updateTimerText(String.format(
"%02d;%02d;%02d;%03d", hours, minutes, seconds, millis))
will raise another error. It should simply be:
((MainFragment) mContext).updateTimerText(...)
I can't help it, I have to suggest to use a different approach, first of all it's a bad idea to keep a reference to the context in a Runnable class.
Second of all, it's bad to cast Context to either Activity or Fragment, it will reduce the code reusability and cause unexpected crashes if the dev is not aware of this casts.
Related
I am implementing a local database using ROOM in android studio. I am having a problem. I am successful in inserting and deleting the data entries into the database. But when I am getting all the data objects from the database then each time I am getting one object less.
When that activity starts then there is no problem but when I am trying to update the recycler view after inserting a new data object into the database then that object is being updated into the recycler view one step after creating a new data object entry and the same problem happens with this also.
below is my complete code:-
package com.example.eventus.DashBoard;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Toast;
import com.example.eventus.ApplicationDatabase.Events.Event;
import com.example.eventus.ApplicationDatabase.Events.EventsAdapter;
import com.example.eventus.ApplicationDatabase.Events.EventsDao;
import com.example.eventus.R;
import com.example.eventus.Singletons.DatabaseSingleton;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class Dashboard extends AppCompatActivity implements View.OnClickListener, DatePickerDialog.OnDateSetListener {
//Declaring the views
private FloatingActionButton fbAddEvent;
private Button btnOKNewEvent, btnCancelNewEvent;
private EditText etDeadlineNewEvent, etTitleNewEvent, etInfoNewEvent;
//For recycler view
private RecyclerView rvEvents;
private RecyclerView.LayoutManager layoutManager;
private List<Event> events;
private EventsAdapter eventsAdapter;
//For alert box
private AlertDialog.Builder alertDialogBuilder;
private AlertDialog alertDialog;
private View alertDialogView;
//For database
private DatabaseSingleton databaseSingleton;
private EventsDao eventsDao;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
//Initializing and setting onclicklisteners on views
init();
//RecyclerView stuff
recyclerViewStuff();
//new event stuff
newEventDialog();
//database stuff
database();
//loadEvents
loadEvents();
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.fb_add_event_dashboard:
alertDialog.show();
}
}
#Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
Calendar mCalendar = Calendar.getInstance();
mCalendar.set(Calendar.YEAR, year);
mCalendar.set(Calendar.MONTH, month);
mCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
String selectedDate = DateFormat.getDateInstance(DateFormat.FULL).format(mCalendar.getTime());
etDeadlineNewEvent.setText(selectedDate);
}
private void init(){
//Initializing the views
rvEvents = findViewById(R.id.rv_events_dashboard);
fbAddEvent = findViewById(R.id.fb_add_event_dashboard);
//Setting onclicklisteners on views
fbAddEvent.setOnClickListener(this);
}
private void recyclerViewStuff() {
//Initializing the recycler view stuffs
layoutManager = new GridLayoutManager(this, 2);
rvEvents.setLayoutManager(layoutManager);
}
private void newEventDialog() {
alertDialogBuilder = new AlertDialog.Builder(Dashboard.this);
alertDialogView = getLayoutInflater().inflate(R.layout.new_event, null);
alertDialogBuilder.setView(alertDialogView);
alertDialog = alertDialogBuilder.create();
alertDialog.setCanceledOnTouchOutside(false);
//Instantiating the view
btnOKNewEvent = alertDialogView.findViewById(R.id.btn_ok_new_event);
etDeadlineNewEvent = alertDialogView.findViewById(R.id.et_deadline_new_event);
btnCancelNewEvent = alertDialogView.findViewById(R.id.btn_cancel_new_event);
etTitleNewEvent = alertDialogView.findViewById(R.id.et_title_new_event);
etInfoNewEvent = alertDialogView.findViewById(R.id.et_info_new_event);
//setting on click listeners for the views in dialog box
btnOKNewEvent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addEvent();
//loadEvents();
refreshEvents();
alertDialog.dismiss();
}
});
btnCancelNewEvent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
alertDialog.dismiss();
}
});
etDeadlineNewEvent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DialogFragment datePicker = new com.example.eventus.DateAndTime.DatePicker();
datePicker.show(getSupportFragmentManager(), null);
}
});
}
private void database(){
//getting the database instance
databaseSingleton = DatabaseSingleton.getInstance();
//getting the events dao
eventsDao = databaseSingleton.getEventsDao(getApplicationContext());
//deleting all previously saved events
eventsDao.deleteAllEvent();
}
private void addEvent() {
String eventTitle, eventInfo, eventDeadline;
eventTitle = etTitleNewEvent.getText().toString();
eventInfo = etInfoNewEvent.getText().toString();
eventDeadline = etDeadlineNewEvent.getText().toString();
//creating an event
Event event = new Event(eventTitle, eventInfo, eventDeadline);
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
eventsDao.createEvent(event);
Toast.makeText(Dashboard.this, "Event Created", Toast.LENGTH_SHORT).show();
}
};
handler.post(runnable);
}
private void loadEvents(){
events = eventsDao.getEvents();
eventsAdapter = new EventsAdapter(events);
rvEvents.setAdapter(eventsAdapter);
}
private void refreshEvents(){
events.clear();
List<Event> tempEventsList = eventsDao.getEvents();
for(int i=0;i<tempEventsList.size();i++){
events.add(tempEventsList.get(i));
}
eventsAdapter.notifyDataSetChanged();
}
}
The problem you are having is realted to concurrency. If you check your code you first call the add event method and place the insertion inside a Runnable, this tells the application to execute at a later time when possible, but it does not execute it inmediately; therefor the code continues its execution, you fetch the events and then, at a later time, the new event is added.
To solve your problem, try to place the call of the method refreshEvents inside the runnable.
Runnable runnable = new Runnable() {
#Override
public void run() {
eventsDao.createEvent(event);
Toast.makeText(Dashboard.this, "Event Created", Toast.LENGTH_SHORT).show();
refreshEvents();
}
};
handler.post(runnable);
EDIT: As correctly said in the comments is not a mult-thread issue, it's the execution time of code fragments inside a single thread.
I'm sure it's going to be a something very obvious that my stupid self couldn't find even after staring at the code for an hour.
I am trying to call the updateImages method in FragmentHome from HomeActivity. I have also created an instance of the class in onCreate but for reasons of my primitive coding knowledge, I am not able to call it. Any help would be greatly appreciated :)
Class that contains said method:
package com.example.youtubethumbnailapp;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.squareup.picasso.Picasso;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import static android.app.Activity.RESULT_OK;
public class FragmentHome extends Fragment {
private FragmentHomeListener listener;
public interface FragmentHomeListener{
void onInputHomeSent(ArrayList<Uri> input);
}
private ImageView video1;
private ImageView video2;
private ImageView video3;
private ImageView video4;
private ImageView video5;
private ImageView video6;
private ImageView video7;
private ImageView video8;
private ImageView video9;
private ImageView video10;
private ImageView addImageButton;
public Uri imageUri;
ArrayList<Uri> uriArrayList = new ArrayList<Uri>();
ArrayList<ImageView> imageViews = new ArrayList<ImageView>();
private int imagesSelected = 0;
#Nullable
#org.jetbrains.annotations.Nullable
#Override
public View onCreateView(#NonNull #org.jetbrains.annotations.NotNull LayoutInflater inflater, #Nullable #org.jetbrains.annotations.Nullable ViewGroup container, #Nullable #org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_home,container,false);
//initialize variables
video1 = v.findViewById(R.id.video1);
imageViews.add(video1);
video2 = v.findViewById(R.id.video2);
imageViews.add(video2);
video3 = v.findViewById(R.id.video3);
imageViews.add(video3);
video4 = v.findViewById(R.id.video4);
imageViews.add(video4);
video5 = v.findViewById(R.id.video5);
imageViews.add(video5);
video6 = v.findViewById(R.id.video6);
imageViews.add(video6);
video7 = v.findViewById(R.id.video7);
imageViews.add(video7);
video8 = v.findViewById(R.id.video8);
imageViews.add(video8);
video9 = v.findViewById(R.id.video9);
imageViews.add(video9);
video10 = v.findViewById(R.id.video10);
imageViews.add(video10);
addImageButton = v.findViewById(R.id.changeViewButton);
addImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
choosePicture();
}
});
return v;
}//end of onCreate
private void choosePicture() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, 1);
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==1 && resultCode==RESULT_OK && null != data && data.getData()!=null){
imageUri = data.getData();
addPicture();
uriArrayList.add(imageUri);
imagesSelected++;
}
}
#Override
public void onAttach(#NonNull #NotNull Context context) {
super.onAttach(context);
if (context instanceof FragmentHomeListener){
listener = (FragmentHomeListener) context;
} else {
throw new RuntimeException(context.toString()
+ "must implement FragmentHomeListener");
}
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
//this is the method I want to call
public void updateImages(ArrayList<Uri> imagesArrayList){
for (int i = 0; i < imagesArrayList.size(); i++){
Picasso.get()
.load(imagesArrayList.get(i))
.fit().centerCrop()
.into(imageViews.get(i));
}
}
private void addPicture(){
Picasso.get()
.load(imageUri)
.fit().centerCrop()
.into(imageViews.get(imagesSelected));
}
private void dataSent(){
listener.onInputHomeSent(uriArrayList);
}
}
Class where I want to call the method from:
package com.example.youtubethumbnailapp;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
public class HomeActivity extends AppCompatActivity implements FragmentHome.FragmentHomeListener, FragmentHistory.FragmentHistoryListener, FragmentSuggested.FragmentSuggestedListener {
private ImageView homeButton;
private ImageView historyButton;
private ImageView playButton;
private Fragment fragmentHome;
private Fragment fragmentHistory;
private Fragment fragmentSuggested;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
homeButton = findViewById(R.id.homeButton);
historyButton = findViewById(R.id.historyButton);
playButton = findViewById(R.id.playButton);
fragmentHome = new FragmentHome();
fragmentHistory = new FragmentHistory();
fragmentSuggested = new FragmentSuggested();
switchToFragmentHome();
homeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switchToFragmentHome();
}
});
historyButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switchToFragmentHistory();
}
});
playButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switchToFragmentSuggested();
}
});
}//end of onCreate
public void switchToFragmentHome(){
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.flFragment, fragmentHome).commit();
}
public void switchToFragmentSuggested(){
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.flFragment, fragmentSuggested).commit();
}
public void switchToFragmentHistory(){
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.flFragment, fragmentHistory).commit();
}
#Override
public void onInputHistorySent(ArrayList<Uri> input) {
//I want to call it from here
}
#Override
public void onInputHomeSent(ArrayList<Uri> input) {
}
#Override
public void onInputSuggestedSent(ArrayList<Uri> input) {
}
}
Since I have instantiated the class, I tried fragmentHome.update but it doesn't show up.
you are creating new instance of fragment. Please check below code:
FragmentHome fragmentHome = new FragmentHome();
You should use it like this:
fragmentHome = new FragmentHome();
Currently, your updateImages method is part of an instance of the class FragmentHome. Since the method doesn't seem to depend on anything, e.g., state, you can make the method static as follows:
public static void updateImages(//args...){
// Your method here
}
Within HomeActivity, you can access this static inner method directly as:
FragmentHome.updateImages(//args...);
P.S.: At the moment, you are likely getting a Non-static method 'updateImages()' cannot be referenced from a static context error.
Note that creating and using updateImages() in this manner is not good practice. It is not "wrong", but it is not efficient in the long run and can cause bugs. (E.g., even if you just declared the method static, you'd likely get a NullPointerException because updateImages() contains a reference to imageViews, an object inside FragmentHome, which may not have been initialized when the method is called in HomeActivity.)
If possible, you should put the independent method updateImages() in a separate utilities class, such that your UI code is as separate from your logic code as possible. This is called "separation of concerns".
I see that you need to use Picasso to set a source image to an ImageView. To do this, you could pass in the ImageView as an argument into the method (disclaimer: if it makes sense for your use case; if it is not going to leak context; etc.), so that the updateImages() method doesn't contain a reference to the imageViews ArrayList that sits in your FragmentHome. Also note that imageViews is currently private, since you've not declared it public.
If you employ this method, your updateImages() or other methods can be reused with higher generality. But of course, there are cases where you just want a wrapper for a method you just can't make very generalized, and that's okay too.
I am trying to create a note-taking app focusing on color-changing.
In one of the activity, I am trying to implement item addition and deletion to the note
picture_of_the_activity.
Item addition obviously works as intended.
The problem is with the deletion, it is very inconsistent: when I delete all the item starting from the last one upward, everything work fine; if I delete items in another order the adapter mess up, do not always delete the correct one and crashes when removing the last item.
I looked it up and found some possible solution (here or in other websites) but couldn't find a solution, or, so I thought.
I created methods inside the adapter addItem() and removeItem() so any changes is done within the class.
Maybe I am misunderstanding a concept or missing something?
Thank you in advance!
some interfaces or protion of the code are missing because I didn't implement some features yet
Activity Code
package com.example.colornoteplus;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
public class CheckListNoteActivity extends AppCompatActivity{
// note editable views
private EditText titleView;
private TextView titleCharacterCount;
private ImageButton colorView;
private RecyclerView contentView;
private FloatingActionButton fab;
CheckListAdapter adapter;
// toolbar
private Toolbar toolbar;
// Current note
private CheckListNote note;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getNoteFromIntent();
note.getContent().add(new CheckListItem("ONE"));
note.getContent().add(new CheckListItem("TWO"));
note.getContent().add(new CheckListItem("THREE"));
note.getContent().add(new CheckListItem("FOUR"));
note.getContent().add(new CheckListItem("FIVE"));
changeViewsColor(0);
}
// Method used to add menus and configure button action
// like OnClickListeners ...
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Create a submenu for sorting purpose
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_check_list_activity,menu);
return super.onCreateOptionsMenu(menu);
}
// get note from the intent
private void getNoteFromIntent(){
if (!getIntent().getStringExtra(Statics.KEY_NOTE_ACTIVITY).equals(Statics.NOTE_DEFAULT_UID)){
note = MySharedPreferences.LoadCheckListNoteFromSharedPreferences(getIntent().getStringExtra(Statics.KEY_NOTE_ACTIVITY),getApplicationContext());
} else {
note = new CheckListNote();
}
}
private void changeViewsColor(int color){
// set the global theme
setTheme(StyleManager.getTheme(color));
// set the appropriate layout
setContentView(R.layout.activity_check_list_note);
// change status bar color
getWindow().setStatusBarColor(getResources().getColor(StyleManager.getThemeColor(color)));
// set up FAB action
fab = findViewById(R.id.fab_add_item);
fab.setOnClickListener(view -> onFabClickListener());
// setting the toolbar
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setBackgroundColor(getResources().getColor(StyleManager.getThemeColor(color)));
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
// setting the note title
titleView = findViewById(R.id.note_title_view);
titleView.setText("");
titleView.setTextColor(getResources().getColor(StyleManager.getThemeColorDark(color)));
titleView.setHintTextColor(getResources().getColor(StyleManager.getThemeColorLight(color)));
// setting the character counter for the note title
titleCharacterCount = findViewById(R.id.note_title_characters);
String m = titleView.getText().toString().trim().length()+ getString(R.string.text_divider)+ getResources().getInteger(R.integer.title_max_length);
titleCharacterCount.setText(m);
titleCharacterCount.setTextColor(getResources().getColor(StyleManager.getThemeColor(color)));
titleView.addTextChangedListener(new TextWatcher()
{
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int aft)
{
}
#Override
public void afterTextChanged(Editable s)
{
// this will show characters remaining
String msg = titleView.getText().toString().length()+ getString(R.string.text_divider)+ getResources().getInteger(R.integer.title_max_length);
titleCharacterCount.setText(msg);
}
});
// setting the color view
colorView = findViewById(R.id.note_color_view);
colorView.setOnClickListener(view -> buildColorPickDialog());
colorView.setBackgroundResource(StyleManager.getBackground(color));
adapter = new CheckListAdapter(getApplicationContext(),note.getContent(),color);
adapter.setOnItemClickListener(new CheckListAdapter.OnItemClickListener() {
#Override
public void onChecked(int position) {
Toast.makeText(CheckListNoteActivity.this, "Checked item: " +position, Toast.LENGTH_SHORT).show();
}
#Override
public void onUnchecked(int position) {
Toast.makeText(CheckListNoteActivity.this, "Unchecked item: " +position, Toast.LENGTH_SHORT).show();
}
#Override
public void onSetPriority(int position) {
}
#Override
public void onSetReminder(int position) {
}
#Override
public void onDelete(int position) {
adapter.removeItem(position);
Toast.makeText(CheckListNoteActivity.this, "List has "+note.getContent().size()+" elements", Toast.LENGTH_SHORT).show();
}
});
contentView = findViewById(R.id.note_content_view);
contentView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
contentView.setAdapter(adapter);
}
private void switchColor(int color){
String tempTitle = titleView.getText().toString().trim();
changeViewsColor(color);
titleView.setText(tempTitle);
}
// build the color picker dialog
private void buildColorPickDialog(){
FragmentPickColor fragment = new FragmentPickColor(new ColorAdapter(),5,note.getColor());
fragment.show(getSupportFragmentManager(),Statics.TAG_FRAGMENT_COLOR_PICK);
fragment.setOnItemClickListener(new ColorAdapter.OnItemClickListener() {
#Override
public void OnClickListener(int position) {
note.setColor(position);
switchColor(position);
fragment.dismiss();
}
#Override
public void OnLongClickListener(int position) {
}
});
}
private void onFabClickListener(){
FragmentAddCheckListItem fragment = new FragmentAddCheckListItem(note.getColor());
fragment.show(getSupportFragmentManager(),Statics.TAG_FRAGMENT_ADD_CHECK_LIST_ITEM);
fragment.setOnClickListener(new FragmentAddCheckListItem.OnClickListener() {
#Override
public void onConfirmClickListener() {
fragment.getItem().setDescription(fragment.getInputText());
adapter.addItem(fragment.getItem(),0);
fragment.dismiss();
}
#Override
public void onSetPriorityClickListener() {
}
#Override
public void onSetDueTimeClickListener() {
FragmentDatePicker datePicker = new FragmentDatePicker();
datePicker.show(getSupportFragmentManager(),Statics.TAG_FRAGMENT_DATE_PICKER);
datePicker.setOnDateSet((year, month, day) -> {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR,year);
c.set(Calendar.MONTH,month);
c.set(Calendar.DAY_OF_MONTH,day);
fragment.getItem().setDueDate(c.getTime().getTime());
fragment.setDueTimeText(DateFormat.getDateInstance().format(new Date(fragment.getItem().getDueDate())));
});
}
});
}
}
Adapter
package com.example.colornoteplus;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
public class CheckListAdapter extends RecyclerView.Adapter<CheckListAdapter.MyViewHolder> {
public CheckListAdapter(Context context,ArrayList<CheckListItem> list, int color) {
this.list = list;
this.color = color;
this.context = context;
}
final private ArrayList<CheckListItem> list;
final private int color;
final private Context context;
private OnItemClickListener listener;
#NonNull
#Override
public CheckListAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new CheckListAdapter.MyViewHolder(LayoutInflater.
from(parent.getContext()).
inflate(R.layout.item_check_list,parent,false));
}
#Override
public void onBindViewHolder(#NonNull CheckListAdapter.MyViewHolder holder, int position) {
CheckListItem currentItem = list.get(position);
holder.background.setBackgroundResource(StyleManager.getBackgroundLight(color));
holder.checkBox.setOnCheckedChangeListener((compoundButton, b) -> {
if (b) listener.onChecked(position);
else listener.onUnchecked(position);
});
holder.title.setTextColor(context.getResources().getColor(StyleManager.getThemeColorDark(color)));
holder.title.setHintTextColor(context.getResources().getColor(StyleManager.getThemeColor(color)));
assert currentItem != null;
holder.title.setText(currentItem.getDescription().trim());
holder.dueTimeText.setTextColor(context.getResources().getColor(StyleManager.getThemeColor(color)));
holder.dueTimeText.setText(currentItem.getDoneDate() != -1 ? DateFormat.getDateInstance().format(new Date(currentItem.getDueDate())) : context.getString(R.string.set_reminder));
holder.dueTimeText.setOnClickListener(view -> listener.onSetReminder(position));
holder.priorityText.setTextColor(context.getResources().getColor(StyleManager.getThemeColor(color)));
holder.priorityText.setText(currentItem.priorityToString(context));
holder.priorityText.setOnClickListener(view -> listener.onSetPriority(position));
holder.delete.setBackgroundResource(StyleManager.getBackground(color));
holder.delete.setOnClickListener(view -> {
// listener.onDelete(position);
removeItem(position);
});
}
#Override
public int getItemCount() {
return list.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
CheckBox checkBox;
ConstraintLayout background;
EditText title;
ImageButton delete;
TextView priorityText,dueTimeText;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
checkBox = itemView.findViewById(R.id.item_check_box);
title = itemView.findViewById(R.id.item_title);
dueTimeText = itemView.findViewById(R.id.item_due_time_text);
priorityText = itemView.findViewById(R.id.item_priority_text);
delete = itemView.findViewById(R.id.item_delete);
background = itemView.findViewById(R.id.item_background);
}
}
public void addItem(CheckListItem item,int position){
if (position < 0){
list.add(item);
notifyItemInserted(list.size()-1);
}
else {
list.add(position,item);
notifyItemInserted(position);
}
}
public void removeItem(int position){
list.remove(position);
notifyItemRemoved(position);
}
public void setOnItemClickListener(OnItemClickListener listener){
this.listener = listener;
}
public interface OnItemClickListener{
void onChecked(int position);
void onUnchecked(int position);
void onSetPriority(int position);
void onSetReminder(int position);
void onDelete(int position);
}
}
public void addItem(CheckListItem item, int position) {
if (position >= 0) {
list.add(position, item);
notifyItemInserted(position);
}
}
public void removeItem(int position) {
if (position >= 0) {
list.remove(position);
notifyItemRemoved(position);
}
}
And in onBindViewHolder use holder.getAdapterPosition() instead of position in your listeners like this:
holder.delete.setOnClickListener(view -> {
// listener.onDelete(position);
removeItem(holder.getAdapterPosition());
});
I am trying to add a second AutoCompleteTextView (that gets objects from a Web API) in a fragment, but it never retrieves anything.
Currently testing on an Emulator, on API level 24. I have previously tried the code for this AutoCompleteTextView in another activity and it worked as intended there.
Fragment Code
package com.advatek.timewin.fragments;
import android.app.AlertDialog;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v7.widget.AppCompatAutoCompleteTextView;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import com.advatek.timewin.MainActivity;
import com.advatek.timewin.R;
import com.advatek.timewin.helper.APICall;
import com.advatek.timewin.helper.APIHelper;
import com.advatek.timewin.helper.AutoSuggestAdapter;
import com.advatek.timewin.helper.JSONHelper;
import com.advatek.timewin.helper.JobSuggestAdapter;
import com.advatek.timewin.models.Employee;
import com.advatek.timewin.models.Function;
import com.advatek.timewin.models.PayPeriod;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.List;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link Clock.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link Clock#newInstance} factory method to
* create an instance of this fragment.
*/
public class Clock extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private Context context;
Handler handler;
Handler jobHandler;
AppCompatAutoCompleteTextView txtEmpSearch;
AppCompatAutoCompleteTextView txtJobSearch;
AutoSuggestAdapter autoAdapter;
JobSuggestAdapter jobAdapter;
private static final int TRIGGER_AUTO_COMPLETE = 100;
private static final long AUTO_COMPLETE_DELAY = 300;
private static List<Function> functionList;
PayPeriod period;
private TextView txtPayWeek;
Spinner spnJobs;
Button btnSignIn;
private OnFragmentInteractionListener mListener;
public Clock() {
// Required empty public constructor
}
public AppCompatAutoCompleteTextView getTextView(){
return txtEmpSearch;
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment Clock.
*/
// TODO: Rename and change types and number of parameters
public static Clock newInstance(String param1, String param2) {
Clock fragment = new Clock();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
context = getContext();
period = new PayPeriod();
functionList = new ArrayList<>();
try{
WeekTask wTask = new WeekTask();
wTask.execute().get();
// JobTask task = new JobTask();
// task.execute();
txtJobSearch = (AppCompatAutoCompleteTextView)getView().findViewById(R.id.txtEmpLookup);
jobAdapter = new JobSuggestAdapter(context, R.layout.support_simple_spinner_dropdown_item);
txtJobSearch.setThreshold(2);
txtJobSearch.setAdapter(jobAdapter);
// Fires when an Employee is selected
txtJobSearch.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
InputMethodManager in = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
in.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
Function job = (Function) parent.getItemAtPosition(position);
((MainActivity)getActivity()).setJob(job);
}
});
txtJobSearch.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
jobHandler.removeMessages(TRIGGER_AUTO_COMPLETE);
jobHandler.sendEmptyMessageDelayed(TRIGGER_AUTO_COMPLETE, AUTO_COMPLETE_DELAY);
}
#Override
public void afterTextChanged(Editable s) {
if(txtJobSearch.getText().toString().equals("")){
}
}
});
jobHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
if (msg.what == TRIGGER_AUTO_COMPLETE) {
if (!TextUtils.isEmpty(txtJobSearch.getText())) {
getJobs(txtJobSearch.getText().toString());
}
}
return false;
}
});
}
catch (Exception ex){
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setTitle("Error");
dialog.setMessage(ex.getMessage());
dialog.show();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_clock, container, false);
txtEmpSearch = view.findViewById(R.id.txtEmpLookup);
txtJobSearch = view.findViewById(R.id.txtJobSearch);
btnSignIn = view.findViewById(R.id.btnSignIn);
return inflater.inflate(R.layout.fragment_clock, container, false);
}
/**
* Gets the Current Pay Period and Sets up the AutoCompleteTextView
*/
private class WeekTask extends AsyncTask<PayPeriod, Void, PayPeriod>{
#Override
protected PayPeriod doInBackground(PayPeriod... payPeriods) {
return new APIHelper().getCurrentPayWeek(JSONHelper.getDateAsInt());
}
#Override
protected void onPostExecute(PayPeriod payPeriod) {
period = payPeriod;
txtPayWeek = getView().findViewById(R.id.txtPayWeekNo);
txtPayWeek.setText(getString(R.string.txtCurrentWeek, payPeriod.getPayWeekNo()));
txtEmpSearch = (AppCompatAutoCompleteTextView) getView().findViewById(R.id.txtEmpLookup);
autoAdapter = new AutoSuggestAdapter(context, R.layout.support_simple_spinner_dropdown_item);
txtEmpSearch.setThreshold(2);
txtEmpSearch.setAdapter(autoAdapter);
// Fires when an Employee is selected
txtEmpSearch.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
InputMethodManager in = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
in.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
Employee emp = (Employee) parent.getItemAtPosition(position);
((MainActivity)getActivity()).setEmployee(emp);
}
});
txtEmpSearch.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
handler.removeMessages(TRIGGER_AUTO_COMPLETE);
handler.sendEmptyMessageDelayed(TRIGGER_AUTO_COMPLETE, AUTO_COMPLETE_DELAY);
}
#Override
public void afterTextChanged(Editable s) {
if(txtEmpSearch.getText().toString().equals("")){
}
}
});
handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
if (msg.what == TRIGGER_AUTO_COMPLETE) {
if (!TextUtils.isEmpty(txtEmpSearch.getText())) {
makeApiCall(txtEmpSearch.getText().toString());
}
}
return false;
}
});
}
}
private void getJobs(String term){
APICall.getJobsByPartial(context, term, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
List<Function> jobs = new ArrayList<>();
try{
JSONArray array = new JSONArray(response);
jobs = new APIHelper().populateFunctionList(array);
jobAdapter.setData(jobs);
jobAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
}
}
The code above does work, the issue was with how I was testing it. I had to use the first AutoCompleteTextView, pick a suggestion, then use the second one. If I tried to use the second one first, it does not work.
I created a small application where I have a list of products and for each of the product I have an expiry time. If the user chooses to like a certain product(showTimerPost), the expiry time of the product will increase lets say 5 second. I tried it with a handler and it actually worked but my app started to run really slow maybe because it was changing the UI every second. I am really stuck with this problem for 1 month. Help will be appreciated.
package com.blueflair.incre;
import com.blueflair.incre.app.AppController;
import com.blueflair.incre.data.FeedItem;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.volley.toolbox.ImageLoader;
public class FeedListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
LocalUserData userLocalStore;
long postExpiry;
String timerFormat;
private int defaultPostIncrementation = 900000;
private List<FeedItem> feedItems;
boolean favourite;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
private long timeDiff;
private final List<ViewHolder> lstHolders;
private int avatarSize;
Handler handler = new Handler();
private Runnable timerRunnable = new Runnable() {
#Override
public void run() {
for (final ViewHolder holder : lstHolders) {
holder.showTimerPost.postDelayed(new Runnable() {
#Override
public void run() {
long currentTime = System.currentTimeMillis();
currentTime--;
holder.showTimerPost.setText(String.valueOf(holder.updateTimeRemaining(currentTime)));
notifyDataSetChanged();
}
}, 2000);
}
}
};
public FeedListAdapter(Activity activity, List<FeedItem> feedItems) {
this.activity = activity;
this.feedItems = feedItems;
lstHolders = new ArrayList<>();
}
#Override
public int getCount() {
return feedItems.size();
}
#Override
public Object getItem(int location) {
return feedItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.feed_item, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
final FeedItem item = feedItems.get(position);
holder = new ViewHolder();
userLocalStore = new LocalUserData(activity);
final User user = userLocalStore.getLoggedInUser();
postExpiry = item.getPostExpiry();
avatarSize = activity.getResources().getDimensionPixelSize(R.dimen.feed_avater_size);
holder.name = (TextView) convertView.findViewById(R.id.userFeedName);
holder.timestamp = (TextView) convertView
.findViewById(R.id.timestamp);
holder.statusMsg = (TextView) convertView
.findViewById(R.id.txtStatusMsg);
holder.profilePic = (ImageView) convertView
.findViewById(R.id.profilePic);
holder.profilePic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Bundle args= new Bundle();
args.putInt("userId", item.getUserId());
Fragment profileViewFragment = new ProfileViewFragment();
profileViewFragment.setArguments(args);
FragmentTransaction ft = ((MainActivity)activity).getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_done, R.anim.slide_out_send);
ft.replace(R.id.container_body, profileViewFragment);
ft.addToBackStack(null);
ft.commit();
}
});
holder.feedImageView = (FeedImageView) convertView
.findViewById(R.id.feedImage1);
String username = "#"+item.getUserName();
holder.name.setText(username);
convertView.setTag(holder);
synchronized ( lstHolders) {
lstHolders.add(holder);
}
// Converting timestamp into x ago format
CharSequence timeAgo = DateUtils.getRelativeTimeSpanString(
Long.parseLong(item.getTimeCreated()),
System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS);
holder.timestamp.setText(timeAgo);
holder.showTimerPost = (Button) convertView.findViewById(R.id.showPostTimer);
handler.post(timerRunnable);
holder.showTimerPost.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
item.setIncrementToExpiry(50000);
notifyDataSetChanged();
}
});
// Chcek for empty status message
if (!TextUtils.isEmpty(item.getPostMessage())) {
holder.statusMsg.setText(item.getPostMessage());
holder.statusMsg.setVisibility(View.VISIBLE);
} else {
// status is empty, remove from view
holder.statusMsg.setVisibility(View.GONE);
}
// Feed image
if (item.getUserImage() != null) {
holder.feedImageView.setImageUrl(item.getUserImage(), imageLoader);
holder.feedImageView.setVisibility(View.VISIBLE);
holder.feedImageView
.setResponseObserver(new FeedImageView.ResponseObserver() {
#Override
public void onError() {
}
#Override
public void onSuccess() {
}
});
} else {
holder.feedImageView.setVisibility(View.GONE);
}
//Setting the timer adapter for the post and their respective contents
holder.setData(item);
return convertView;
}
private class ViewHolder {
FeedItem item;
public TextView name;
public TextView timestamp;
public TextView statusMsg;
public ImageView profilePic;
public FeedImageView feedImageView;
public Button showTimerPost;
public void setData(FeedItem item) {
this.item = item;
updateTimeRemaining(System.currentTimeMillis());
}
public String updateTimeRemaining(long currentTime) {
timeDiff = (item.getPostExpiry()+400000000) - currentTime;
if (timeDiff > 0) {
timerFormat = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(timeDiff),
TimeUnit.MILLISECONDS.toMinutes(timeDiff) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeDiff)),
TimeUnit.MILLISECONDS.toSeconds(timeDiff) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeDiff)));
showTimerPost.setText(timerFormat);
return timerFormat;
} else {
//Delete feed items when post is expired
showTimerPost.setText("Expired!");//only to explimify
}
return timerFormat;
}
}
}