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;
}
Related
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 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?
I've got problem with my ListView. I'm creating new object and add it to the database by clicking button in the first fragment. In the second fragment I've got listview with objects from my database. Everything works fine but listView in the second fragment doesn't refresh - I see new objects only after restarting app. All solutions like : notifyDataSetChanged don't work :/
Here's my adapter from first fragment:
public class ConcertAdapter extendsRecyclerView.Adapter<ConcertAdapter.MyViewHolder> {
private static final String FRAGMENT_TAG = "fragmentTag";
private static final String TAG = ConcertAdapter.class.getSimpleName() ;
private LayoutInflater inflater;
private Context context;
private List<Concert> concertList = new ArrayList<>();
private DatabaseHelper mDatabaseHelper = null;
private int selectedRecordPosition = -1;
private MainActivity mActivity;
public ConcertAdapter(Context context, List<Concert> concerts, MainActivity mainActivity) {
this.inflater = LayoutInflater.from(context);
this.concertList = concerts;
this.context = context;
this.mActivity = mainActivity;
}
public void setListConcert(ArrayList<Concert> concertList) {
this.concertList = concertList;
notifyItemRangeChanged(0, concertList.size());
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.from(parent.getContext()).inflate(R.layout.concert_item, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
final float screenWidthPx = holder.itemView.getResources().getDisplayMetrics().widthPixels;
Concert current = concertList.get(position);
Log.d("mLog", current.getUrl());
holder.mImage.setImageUrl(current.getUrl(), MySingleton.getInstance().getImageLoader());
holder.mImage.getLayoutParams().height = (int) (screenWidthPx * 0.50);
holder.mFav_btn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked) {
final Concert favConcert = new Concert();
favConcert.setTitle(concertList.get(position).getTitle());
favConcert.setContent(concertList.get(position).getContent());
favConcert.setDate(concertList.get(position).getDate());
favConcert.setUrl(concertList.get(position).getUrl());
try {
final Dao<Concert, Integer> concertDao = getHelper().getConcertDao();
concertDao.create(favConcert);
}catch (SQLException e) {
e.printStackTrace();
}
}
}
});
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date concertDate = new Date();
try {
concertDate = format.parse(current.getDate());
} catch (ParseException e) {
e.printStackTrace();
}
DateTime dt = new DateTime();
DateTime currentDate = dt.withZone(DateTimeZone.forID("Europe/Warsaw"));
int days = Days.daysBetween(new DateTime(currentDate), new DateTime(concertDate)).getDays();
String s = String.valueOf(days);
holder.mDate_btn.setText(s + " dni");
if (s.equals("0")) {
holder.mDate_btn.setText("dziś :)");
}
}
#Override
public int getItemCount() {
return concertList.size();
}
public void setConcerts(List<Concert> concerts) {
concertList = new ArrayList<>(concerts);
}
public void showDisplay(int position) {
Bundle bundle = new Bundle();
bundle.putInt("position", position);
bundle.putString("content", concertList.get(position).getContent());
bundle.putString("date", concertList.get(position).getDate());
bundle.putString("url", concertList.get(position).getUrl());
bundle.putString("title", concertList.get(position).getTitle());
Fragment fragment = new DisplayConcertFragment();
fragment.setArguments(bundle);
mActivity.replaceFragment(fragment);
}
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public NetworkImageView mImage;
public Button mDate_btn;
public TextView mBubble;
public ToggleButton mFav_btn;
public ImageView mBubbleImage;
private ConcertFragment mConcertFragment;
public MyViewHolder(View itemView) {
super(itemView);
mImage = (NetworkImageView) itemView.findViewById(R.id.concerts_niv);
mDate_btn = (Button) itemView.findViewById(R.id.date_btn);
mImage.setOnClickListener(this);
mFav_btn = (ToggleButton) itemView.findViewById(R.id.fav_btn);
}
#Override
public void onClick(View v) {
showDisplay(getAdapterPosition());
//ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
Toast.makeText(context, "TEST", Toast.LENGTH_LONG).show();
}
public Concert removeItem(int position) {
final Concert concert = concertList.remove(position);
notifyItemRemoved(position);
return concert;
}
}
private DatabaseHelper getHelper() {
if (mDatabaseHelper == null) {
mDatabaseHelper = OpenHelperManager.getHelper(context,DatabaseHelper.class);
}
return mDatabaseHelper;
}
Here's my second adapter:
public class FavAdapter extends ArrayAdapter {
private LayoutInflater mInflater;
private List mRecords;
private Dao<Concert, Integer> concertDao;
private Button mDateButton;
private NetworkImageView mImage;
public FavAdapter(Context context, int resource, List objects, Dao<Concert, Integer> concertDao) {
super(context, resource, objects);
this.mRecords = objects;
this.concertDao = concertDao;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null)
convertView = mInflater.inflate(R.layout.concert_item, parent, false);
if(mRecords.get(position).getClass().isInstance(new Concert())){
final Concert concert = (Concert) mRecords.get(position);
mImage =((NetworkImageView)convertView.findViewById(R.id.concerts_niv));
mImage.setImageUrl(concert.getUrl(), MySingleton.getInstance().getImageLoader());
final float screenWidthPx = mImage.getResources().getDisplayMetrics().widthPixels;
mImage.getLayoutParams().height = (int) (screenWidthPx * 0.50);
mDateButton = (Button) convertView.findViewById(R.id.date_btn);
Date concertDate = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
concertDate = format.parse(concert.getDate());
} catch (ParseException e) {
e.printStackTrace();
}
DateTime dt = new DateTime();
DateTime currentDate = dt.withZone(DateTimeZone.forID("Europe/Warsaw"));
int days = Days.daysBetween(new DateTime(currentDate), new DateTime(concertDate)).getDays();
String s = String.valueOf(days);
mDateButton.setText(s + " dni");
if (s.equals("0")) {
mDateButton.setText("dziś :)");
}
// ((TextView)convertView.findViewById(R.id.teacher_tv)).setText(studentDetails.teacher.teacherName);
}
return convertView;
}
}
And here's my second fragment with ListView:
public class FavFragment extends Fragment {
private static final String TAG = FavFragment.class.getSimpleName() ;
private DatabaseHelper mDatabaseHelper = null;
private ListView mListView;
private int selectedRecordPosition = -1;
private Dao<Concert, Integer> concertDao;
private List<Concert> concertList;
private MainActivity mActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_fav_layout, container, false);
mListView = (ListView)v.findViewById(R.id.concerts_lv);
mActivity = (MainActivity) getContext();
try {
concertDao = getHelper().getConcertDao();
concertList = concertDao.queryForAll();
FavAdapter adapter = new FavAdapter(getContext(), R.layout.concert_item, concertList, concertDao);
mListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
mListView.invalidateViews();
mListView.refreshDrawableState();
} catch (SQLException e) {
e.printStackTrace();
}
Log.e(TAG, "onCreateView notify");
return v;
}
private DatabaseHelper getHelper() {
if (mDatabaseHelper == null) {
mDatabaseHelper = OpenHelperManager.getHelper(getContext(), DatabaseHelper.class);
}
return mDatabaseHelper;
}
#Override
public void onDestroy() {
super.onDestroy();
if (mDatabaseHelper != null) {
OpenHelperManager.releaseHelper();
mDatabaseHelper = null;
}
}
}
Here's my first fragment
public class ConcertFragment extends Fragment implements MyBackPressed {
private static final String FRAGMENT_TAG = "fragmentTag";
private static final String TAG = ConcertFragment.class.getSimpleName() ;
public ProgressBar progress;
private ConcertLoader concertLoader;
private RecyclerView recyclerView;
private Context mContext;
private android.support.v4.app.FragmentManager mFragmentManager;
private MainActivity mActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
JodaTimeAndroid.init(getContext());
View v = inflater.inflate(R.layout.fragment_concert_layout, container, false);
progress = (ProgressBar) v.findViewById(R.id.progressBar);
recyclerView = (RecyclerView) v.findViewById(R.id.concerts_rv);
concertLoader = new ConcertLoader(ConcertFragment.this);
mActivity = (MainActivity) getContext();
futureConcerts();
return v;
}
public void futureConcerts() {
concertLoader.execute();
getActivity().getWindow().getDecorView().getRootView().setClickable(false);
}
public void notifyAboutListCreation(List<Concert> res) {
ConcertAdapter adapter = new ConcertAdapter(getActivity().getApplicationContext(), res, mActivity);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
progress.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
}
#Override
public void onBackPressed() {
getActivity().finish();
}
}
I had similar problems a while ago. Are you triggering any UI updates from non-UI threads? Maybe from within listeners? Try using the following code where the UI updates are triggered.
runOnUiThread(new Runnable(){
#Override
public void run(){
...
adapter.notifyDataSetChanged();
mListView.invalidateViews();
mListView.refreshDrawableState();
...
}
});
Personally, I now have started to wrap any problematic code blocks in a generic try-catch block that catches Exception and see if there are any exceptions I migh thave overseen (using logcat on terminal with tag filter).
(Cannot comment yet, so answering in this way)
How can I refresh the view of a fragment, when the back button is pressed?
I have tried this in the onResume method of the fragment but it doesn't work.
OK, here is the code
#SuppressWarnings("unused")
public class RestaurantMenuFragment extends Fragment {
private static final String TAG = "MenuItemsFragment";
private static final String CATEGORIES_KEY = "categories";
private static final String SELECTED_CATEGORY_ID_KEY = "category";
private static final String RESTAURANT_KEY = "restaurant123";
private static final String RESTAURANT_KCITY = "city";
private Spinner mCategoriesSpinner;
private ArrayAdapter<CategoriesResponse.Category> mCategoriesAdapter;
private ListView mListView;
private List<MenuItem> mItems;
private MenuItemsAdapter mItemsAdapter;
private EmptyLayout mEmptyLayout;
private Restaurant mRestaurant;
private int mCategoryId;
private List<CategoriesResponse.Category> mCategories;
private RestaurantActivity mActivity;
private MainApplication mApplication;
private CategoriesResponse mCategoriesResponse;
private ActionBar mActionBar;
private Gson mGson;
int categ;
private ObjectGetter mObjectGetter;
public static RestaurantMenuFragment newInstance(Restaurant restaurant) {
RestaurantMenuFragment fragment = new RestaurantMenuFragment();
Bundle args = new Bundle();
args.putString(RESTAURANT_KEY, new Gson().toJson(restaurant));
String dd=restaurant.city;
Log.i("dd12", dd);
fragment.setArguments(args);
return fragment;
}
public RestaurantMenuFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = (RestaurantActivity) getActivity();
mApplication = (MainApplication) mActivity.getApplication();
mActionBar = mActivity.getSupportActionBar();
mGson = new Gson();
mObjectGetter = new ObjectGetter();
mCategories = new ArrayList<CategoriesResponse.Category>();
Log.i("mCategories",""+mCategories);
mItems = new ArrayList<MenuItem>();
Log.i("12345",""+mItems);
mItemsAdapter = new MenuItemsAdapter(getActivity(), mItems);
Bundle args = getArguments();
if (args != null) {
mRestaurant = mGson.fromJson(args.getString(RESTAURANT_KEY),
Restaurant.class);
}
if (savedInstanceState != null) {
mRestaurant = mGson.fromJson(
savedInstanceState.getString(RESTAURANT_KEY),
Restaurant.class);
mCategoryId = savedInstanceState.getInt(SELECTED_CATEGORY_ID_KEY);
mCategoriesResponse = mGson.fromJson(
savedInstanceState.getString(CATEGORIES_KEY),
CategoriesResponse.class);
}
assert mRestaurant != null;
updateCart();
}
public void updateCart() {
View view = mActionBar.getCustomView();
Button cartButton = (Button) view.findViewById(R.id.cartButton);
int nOfItems = 0;
if (mApplication.isCartCreated()) {
nOfItems = mApplication.getCart().getNOfAllItems();
}
cartButton.setText(String.format("%d", nOfItems));
if (nOfItems > 0) {
cartButton.setEnabled(true);
} else {
cartButton.setEnabled(false);
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Gson gson = new Gson();
outState.putString(RESTAURANT_KEY, gson.toJson(mRestaurant));
outState.putInt(SELECTED_CATEGORY_ID_KEY, mCategoryId);
outState.putString(CATEGORIES_KEY, gson.toJson(mCategoriesResponse));
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onViewCreated(view, savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.spinner_list, container, false);
RestaurantActivity activity = (RestaurantActivity) getActivity();
String myDataFromActivity = activity.getMyData();
String myDataFromActivity1 = activity.getMyData1();
Log.i("myDataFromActivity",myDataFromActivity);
Log.i("myDataFromActivity1",myDataFromActivity1);
categ=Integer.parseInt(myDataFromActivity1);
mListView = (ListView) view.findViewById(R.id.list122334);
mListView.setAdapter(mItemsAdapter);
Log.d(TAG,"Querying items url "
+ Urls.menuItemsQuery(mRestaurant.id,categ));
mEmptyLayout = EmptyLayout.with(getActivity()).to(mListView)
.setEmptyMessage(R.string.categories_empty_message)
.showLoading();
loadItems();
return view;
}
private void loadItems() {
mEmptyLayout.showLoading();
mItems.clear();
mObjectGetter.getJsonObjectOrDialog(mActivity,
Urls.menuItemsQuery(mRestaurant.id, categ),
ItemsResponse.class,
new ObjectGetter.OnFinishedListener<ItemsResponse>() {
#Override
public void onFinishedLoadingObject(
ItemsResponse itemsResponse) {
mEmptyLayout.showEmpty();
if (itemsResponse != null
&& itemsResponse.items != null) {
mItems.addAll(itemsResponse.items);
}
mItemsAdapter.notifyDataSetChanged();
}
});
}
private class MenuItemsAdapter extends ArrayAdapter<MenuItem> {
private static final String TAG = "MenuItemsAdapter";
public MenuItemsAdapter(Context context, List<MenuItem> menuItems) {
super(context, 0, menuItems);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final MenuItem menuItem = getItem(position);
View view = convertView;
final ViewHolder viewHolder;
LayoutInflater inflater;
if (convertView == null) {
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.menu_item, parent, false);
viewHolder = new ViewHolder();
viewHolder.name = (TextView) view.findViewById(R.id.name);
viewHolder.description = (TextView) view.findViewById(R.id.description);
viewHolder.price = (TextView) view.findViewById(R.id.price);
viewHolder.add = (Button) view.findViewById(R.id.add);
viewHolder.selectedView = view.findViewById(R.id.selectedView);
viewHolder.remove = (Button) view.findViewById(R.id.remove);
viewHolder.total = (TextView) view.findViewById(R.id.itemTotal);
viewHolder.quantity = (TextView) view.findViewById(R.id.quantity);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
try
{
viewHolder.name.setText(menuItem.name);
viewHolder.description.setText(menuItem.description);
viewHolder.price.setText(String.valueOf(menuItem.price));
}catch(NullPointerException e){
e.printStackTrace();
}
viewHolder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mApplication.createNewCartIfPossibleAndAskIfNot(
getActivity(), mRestaurant,
new MainApplication.OnCreateCartListener() {
#Override
public void onCreateCart(Cart cart) {
cart.addOne(menuItem);
updateItemFromCart(menuItem, viewHolder);
updateCart();
}
});
}
});
viewHolder.remove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!mApplication.isCartCreated()) {
return;
}
mApplication.getCart().removeOne(menuItem);
updateItemFromCart(menuItem, viewHolder);
updateCart();
}
});
return view;
}
private void updateItemFromCart(MenuItem menuItem, ViewHolder viewHolder) {
if (!mApplication.isCartCreated()) {
return;
}
int quantity = mApplication.getCart().getNOfItemsOfType(menuItem);
if (quantity > 0) {
viewHolder.selectedView.setVisibility(View.VISIBLE);
} else {
viewHolder.selectedView.setVisibility(View.GONE);
}
viewHolder.quantity.setText(String.valueOf(quantity));
viewHolder.total.setText(String.valueOf(quantity
* menuItem.price));
}
class ViewHolder {
TextView name;
TextView description;
TextView price;
Button add;
View selectedView;
Button remove;
TextView total;
TextView quantity;
}
}
#Override
public void onResume() {
super.onResume();
updateCart();
mItems.clear();
if (mItemsAdapter != null) {
mItemsAdapter.notifyDataSetChanged();
}
}
#Override
public void onDestroy() {
if (mObjectGetter != null) {
mObjectGetter.stopRequests();
}
super.onDestroy();
}
}
Now, i want to update the listvieww data when the user pressed the back button. I set the new loadItems() method in the onResume() Method of the Fragment. This Method is called but the old listview data appears and new data also appears...
Back button should be handled from Activity.
You can override onBackPressed in Activity and call a function on corresponding fragment to reloadItems().
Here are your 3 options I could think of.
Get reference to Fragment and call function to reLoadItems and its better to define an interface for this communication which fragment implements.
Better solution than first one. Add a LocalBroadcast which Activity broadcasts and your fragment listens and updates data on receiving broadcast.
Example for this :
http://luboganev.github.io/blog/messaging-with-localbroadcastmanager/
Otto event bus where both activity and fragment classes are connected to the event bus and they activity publishes event and fragment subscribes to it. This is what I am using for something similar in my application. (But I have pretty frequent asynchronous events that come along. SO I am using this. 2nd option might be sufficient in your case).
Example for this :
http://www.vogella.com/tutorials/JavaLibrary-EventBusOtto/article.html
As ramesh already mentioned, back button handling happens in your activity class that holds the fragments. Here is a simple example, how you can handle these back button events for your fragment.
Activity Code:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
boolean returnSuperKeyDown = true;
if(keyCode == KeyEvent.KEYCODE_BACK){
Fragment fragment = getYourCurrentFragment();
if (fragment instanceof YourFragment) {
returnSuperKeyDown = ((YourFragment) fragment).onFragmentKeyDown();
}
}
if (returnSuperKeyDown) {
return super.onKeyDown(keyCode, event);
} else {
return true;
}
}
YourFragment Method:
public boolean onFragmentKeyDown() {
updateYourFragment();
return false;
}
#Rithe, #sunder sharma
As per me there is simple to refresh the fragment when come back from other fragment,
We just have to override the onActivityCreated Method for refresh fragment.
Like as
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//your code which you want to refresh
loadItems();
}
You can also update/refresh the fragment using onStart() method.
public void onStart(){
super.onStart();
//update your fragment
}
This worked fine for me.
call your loadItem() method onHiddenChanged(boolean hidden)method.onHiddenChanged is overrided method
I came across a very awkward behaviour in my fragment.
The output is:
this.userID: 0
and
RoomChatFragment userID: 14
But in this case, this.userID should also be 14. Is my context lost somewhere, while passing it as a parameter? I can't explain myself this behaviour. I don't think getActivity() returns null, otherwise there would be an exception.
// Fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
context = getActivity();
user = new UserHandler(context);
messageDatabase = MessageDatabase.getInstance(context);
Log.i("debug", "RoomChatFragment userID: " + user.getUserID());
}
// UserHandler
public class UserHandler {
private final SharedPreferences sharedPrefs;
private final SharedPreferences sharedPrefsPreferences;
private Context context;
public UserHandler(Context context) {
sharedPrefs = context.getSharedPreferences("USER", 0);
sharedPrefsPreferences = PreferenceManager.getDefaultSharedPreferences(context);
this.context = context;
}
public int getUserID() {
return sharedPrefs.getInt("userID", 0);
}
public void setUserID(int userID) {
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putInt("userID", userID);
editor.apply();
}
}
// Database
public class MessageDatabase extends AbstractDatabase {
private int userID;
protected static MessageDatabase instance;
public MessageDatabase(Context context) {
super(context);
UserHandler user = new UserHandler(context);
userID = user.getUserID();
}
public static MessageDatabase getInstance(Context context) {
if (MessageDatabase.instance == null) {
MessageDatabase.instance = new MessageDatabase(context);
}
return MessageDatabase.instance;
}
// ....
#Override
protected Message cursorToObject(Cursor cursor) {
Log.i("debug", "this.userID: " + this.userID);
}
}
// AbstractDatabase
public abstract class AbstractDatabase {
protected Context context;
protected AbstractDatabase(Context context) {
this.context = context;
}
}
I'm not absolutely sure what's going on here (your code is really messy). But it seems you're using a different key for the preference:
context.getSharedPreferences("USER", 0);
sharedPrefs.getInt("userID", 0);
Stupid me! The problem is the singleton design pattern of my database design. My MessageDatabase.instance is cached and holds an old Context object, where the userID of my SharedPreferences is 0.
I've updated my method like this and it seems to work:
public static MessageDatabase getInstance(Context context) {
if (MessageDatabase.instance == null || userID == 0) {
MessageDatabase.instance = new MessageDatabase(context);
}
return MessageDatabase.instance;
}