Fragment use is mandatory in Android 4.4 - android

As per the Android 4.4 developer guideline we have to use Fragment in each activity. If we make inner fragment class non-static then Android will crash our app when it comes from background to foreground so we need to make the fragment class static. In that case all the variables and classes which have been used in the fragment class (other than fragment class variable) should be static.
I think that will consume more VM memory and the app will be unstable. Can anyone suggest if I am right? Or suggest if there is other way to overcome that problem.
Here is the snippet of code.
public class MainActivity extends ActionBarActivity {
// Video variable
MediaRecorder recorder;
// Networking variables
public static String SERVERIP="";
public static final int SERVERPORT = 6775;
private Handler handler = new Handler();
private ServerSocket serverSocket;
public static SurfaceHolder mHolder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
// User Interface Elements
VideoView mView;
TextView connectionStatus;
/** Called when the activity is first created. */
public PlaceholderFragment() {
}
NotificationManager notificationManager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onViewCreated(view, savedInstanceState);
Button btn = (Button)view.findViewById(R.id.notifybtnID);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
// Define UI elements
mView = (VideoView) view.findViewById(R.id.video_preview);
// connectionStatus = (TextView) findViewById(R.id.connection_status_textview);
mHolder = mView.getHolder();
// mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
SERVERIP = "192.168.1.126";
// Run new thread to handle socket communications
Thread sendVideo = new Thread(new SendVideoThread());
sendVideo.start();
}
public static class SendVideoThread implements Runnable{
public void run(){
// From Server.java
try {
if(SERVERIP!=null){
handler.post(new Runnable() {
#Override
public void run() {
// connectionStatus.setText("Listening on IP: " + SERVERIP);
}
});
}

Related

how to change fragment views programmatically from the parent activity

I am having a fragment that contains for example one button, I want to allow the Activity containing the fragment to change this button view like for example color and title or src Image.
What's the best way to do that ?
Update : sorry If I wasn't clear enough but I want the activity to change the whole view as it's likes , like setting the padding, the color or anything.
It will create the view programmatically and the fragment should replace the old view by the new one and change the view's ID so that the fragment code isn't affected. And If i created methods in the fragment that takes these views when should the Main activity call them ? since the activity has to wait for the layout of the fragment to be created.
1. You must get you fragment from your activity
val fragment = supportFragmentManager.findFragmentByTag("tag")
or
val fragment = supportFragmentManager.findFragmentById(R.id.fragment)
2. Create a method that will do what you wants in you fragment and call this method from the activity
fragment.hideButton()
or you can use interface
Try this way according to your requirement
public abstract class BaseFragment extends Fragment {
BaseActivity yourActivity;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
yourActivity = (BaseActivity) context;
}
#Override
public void onDetach() {
yourActivity = null;
super.onDetach();
}
public void refreshview(){}
public void setDada(Data data){}
#override
publicn void onStart(){
yourActivity.setCurrentOpenedFragment(this);
}
}
Create the BaseActivity class
public abstract class BaseActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void setCurrentOpenedFragment(BaseFragment currentFragment){}
}
Extends the BaseFragment in your fragment i.e.
public class YourFragment extends BaseFragment{
View view;
Button button;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment, container, false);
button = (Button)view.findViewById(R.id.button);
return view;
}
#override
publicn void onStart(){
super.onStart();
//yourActivity.setCurrentOpenedFragment(this);
}
Data data;
#override
public void setDada(Data data){
this.data = data;
}
#Override
public void refreshview() {
button.setcolor(data.getcolor());
}
}
Write the below line of code in your Activity class
public class YourActivity extends BaseActivity{
public static final byte NONE = -1;
public static final byte HOME = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_activity);
changeFragment(new YourFragment(), HOME);
initview();
}
public void initview(){
Button b = (Button)findViewById(R.id.button);
b.setOnClickListener(new OnClickListener(){
if(currentFragmentOnDrawer != null){
Data data = new Data();
data.setColor(getResource().getcolor(R.color.red));
currentFragmentOnDrawer.setDada(data);
currentFragmentOnDrawer.refreshview()
}
});
}
BaseFragment currentFragmentOnDrawer;
#Override
public void setCurrentOpenedFragment(BaseFragment currentFragment) {
super.setCurrentOpenedFragment(currentFragment);
this.currentFragmentOnDrawer = currentFragment;
}
public void changeFragment(Fragment targetFragment, byte state) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.replace(R.id.main_fragment, targetFragment, "" + state);
ft.addToBackStack("" + state);
ft.commit();
}
}
Hope it will help for you

Creating Multiple event callbacks from fragment to the activity

I was able to create a single event callback from a fragment to the activity. However, I have problem with creating two event callbacks from the same fragment.
Basically, I have a button on the fragment1 layout, when click on it, it will execute something in mainactivity, and then, it changes hide the Button at fragment1 layout, and then I need to send a Boolean from the fragment to activity, then initiate fragment2.
How can I implement the 2nd callback interface in the mainacativity.
Here is my code:
at Fragment1:
public class Fragment1 extends Fragment{
private static final String TAG = "Fragment1";
Boolean in1, in2;
Button btn1;
ListenerA mListenerA;
public interface ListenerA{
public void methodA(Boolean in1);
};
ListenerB mListenerB;
public interface ListenerB{
public void methodB(Boolean in2);
};
#Override
public void onAttach(Context context) {
super.onAttach(context);
if(context instanceof ListenerA)
mListenerA = (ListenerA)context;
if(context instanceof ListenerB)
mListenerB = (ListenerB)context;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View myView = inflater.inflate(R.layout.fragment1, container, false);
btn1 = (Button) myView.findViewById(R.id.btn1_ID);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListenerA.methodA(true);
}
});
return myView;
}
public void showBtnMethod (Boolean showBtn){
if (showBtn==false) {
btn1.setVisibility(View.INVISIBLE);
mListenerB.methodB(true); //***** problematic line
}
}
}
and the code in the main activity is below. please note that on the first line I was able only to implement one method from the fragment.
public class MainActivity extends AppCompatActivity implements Fragment1.ListenerA {
private static final String TAG = "MainActivity";
public Fragment1 mFragment1;
public Fragment2 mFragment2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
mFragment1 = new Fragment1();
transaction1.replace(R.id.content_fragment_ID, mFragment1);
transaction1.commit();
}
}
// this gets called by ListenerA when click on the button
public void methodA(Boolean in){
if (in==true){
Toast.makeText(MainActivity.this, "mMethodA Executed", Toast.LENGTH_SHORT).show();
triggerShowMethod();
}
};
private void triggerShowMethod(){
mFragment1.showBtnMethod(false);
};
// Problematic section is below
public void methodB(Boolean in){
if (in==true){
FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction();
mFragment2 = new Fragment2();
transaction2.replace(R.id.content_fragment_ID, mFragment2);
transaction2.commit();
Toast.makeText(MainActivity.this, "mMethodB Executed", Toast.LENGTH_LONG).show();
}
};
}
You can simply consolidate both interfaces into one:
public interface Listener{
public void methodA(Boolean in1);
public void methodB(Boolean in2);
};
and in your MainActivity:
public class MainActivity extends AppCompatActivity implements Fragment1.Listener
Your activity doesn't implement ListenerB.
public class MainActivity extends AppCompatActivity implements Fragment1.ListenerA, Fragment1.ListenerB {
}

Grid.Invalidate in Fragment from FragmentActivity

I am nuebie in Android. I suppose i am try run code from non UI thread. How i can update my grid in Fragment. I have activity SimpleImageActivity. In this Activity i am waiting Back key and I am trying update my data in GridView. Method invalidate() postInvalidate() nothing doing.
private Handler handler;
protected OnBackPressedListener onBackPressedListener;
public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
this.onBackPressedListener = onBackPressedListener;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fragment fr;
String tag= GridViewFragment.class.getSimpleName();
fr = getSupportFragmentManager().findFragmentByTag(tag);
if (fr == null) {
fr = new GridViewFragment();
}
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, fr, tag).commit();
}
#Override
public void onBackPressed() {
if (onBackPressedListener != null){
// ...some code...
handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
System.out.println("[VAN] I am in Runnable");
GridView gV = (GridView)findViewById(R.id.grid); // gV - links to my GridView and not null here
gV.invalidate(); //this code nothing doing
gV.postInvalidate(); //this code nothing doing too
}
}, 0);
onBackPressedListener.onBackPres(); // event Back key for fragment
}
In my GridViewFragment I am trying execute gridView.invalidate too, but in fragment below gridView=null
public class GridViewFragment extends AbsListViewBaseFragment implements OnBackPressedListener {
public GridView gridView;
private FragmentActivity activity;
View rootView;
public GridViewFragment() {
this.activity = getActivity();
}
#Override
public void onBackPres() {
new Thread(new Runnable() {
public void run() {
updateScreen();
// I am try this
// gridView.invalidate() there not working, because gridView=null
//
System.out.println("[VAN] updateScreen");
}
}).start();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
activity = getActivity();
((SimpleImageActivity)activity).setOnBackPressedListener(new GridViewFragment());
rootView = inflater.inflate(R.layout.fragment_image_grid, container, false);
gridView = (GridView) rootView.findViewById(R.id.grid);
// ... some code ...
}
private void updateScreen(){
gridView.postInvalidate(); // error because there gridView=null
}
How i can update my GridView? When triggering method public void onBackPres() { in fragment gridView.invalidate - don't working because gridView = null.
When in activity use handler.postDelayed(new Runnable() { gV return my GridView, but
gV.invalidate();
gV.postInvalidate();
nothing doing and execute without any errors.
A found the answer on my own question
handler = new Handler();
handler.post(new Runnable() {
public void run() {
GridView gV = (GridView)findViewById(R.id.grid);
gV.invalidateViews(); //this works fine
}
});
Using invalidateViews() instead invalidate()

Trying to access a Fragment from another thread to change TextView text

I am making an app that is using Fragments and wish to change the text in a TextView based on a message received in a client thread communicating with a laptop. The client server communication is no issue as the client thread is receiving the strings just fine.
I can't seem to properly figure out how to access the fragments TextView and alter its text.
Here is how I am currently trying to do so:
class ClientThread implements Runnable {
public void run() {
mHandler.post(new Runnable() {
#Override
public void run() {
LivingRoomFragment frag = (LivingRoomFragment)getSupportFragmentManager().findFragmentById(R.id.LivingRoomFragment);
frag.setText("Inside ClientThread right now");
}
});
}
}
public static class LivingRoomFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "section_number";
TextView temp;
public LivingRoomFragment(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_room_control_fragment1, container, false);
temp = (TextView) rootView.findViewById(R.id.textView5);
MainActivity main = new MainActivity();
new Thread(main.new ClientThread(requests)).start();
return rootView;
}
public void setText(String s){
temp.setText(s);
}
}
In this case, MainActivity is the activity extending FragmentActivity.
I'm using an emulator and the app always crashing saying there was a null pointer exception at the line using frag.setText("Inside ClientThread right now"), which I believe means that the instance of LivingRoomFragment is null. It is to my understanding so far that this is supposed to be executed using a Handler because you cannot access the UI from a thread without using a method like this.
What am I doing wrong?
I am not sure, try
MainActivity main = (MainActivity)getActivity;
instead of
MainActivity main = new MainActivity();
okay Toast.
now here is your Solution.
create Broadcast Receiver in your Fragments.
create your action,action is an key which diffrenciat your broadcast.
use below sample code.(you do not have post more code,so it may not ecxatly what you want okay?)
class ClientThread implements Runnable {
private Handler mHandler;
public void run() {
mHandler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent("my_action");
intent.putExtra("message", "TEXT_YOU_WANT_TO_SET");
sendBroadcast(intent);
// LocalBroadcastManager manager = LocalBroadcastManager
// .getInstance(context);
// LivingRoomFragment frag = (LivingRoomFragment)
// getSupportFragmentManager()
// .findFragmentById(R.id.LivingRoomFragment);
// frag.setText("Inside ClientThread right now");
}
});
}
}
public static class LivingRoomFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "section_number";
TextView temp;
private MyBroadCastReceiver broadCastReceiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
broadCastReceiver = new MyBroadCastReceiver();
getActivity().registerReceiver(broadCastReceiver,
new IntentFilter("my_action"));
}
public LivingRoomFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.activity_room_control_fragment1, container, false);
temp = (TextView) rootView.findViewById(R.id.textView5);
MainActivity main = new MainActivity();
new Thread(main.new ClientThread(requests)).start();
return rootView;
}
public void setText(String s) {
temp.setText(s);
}
private class MyBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent intent) {
// chaneg the TextView text here
if (intent.getAction() != null
&& intent.getAction().equalsIgnoreCase("my_action")) {
temp.setText(intent.getStringExtra("message"));
}
}
}
}
good luck.

pass string from fragment main activity to fragments activity in viewpager

i wanna pass a string to all fragment(child) from fragment activity (main), may be this picture can explain what exactly what i want to do
https://dl.dropboxusercontent.com/u/57465028/SC20140205-163325.png
so, from above picture...i wanna pass a string from edittext by press a button to all activity in viewpager....how could i do that?
i tried to follow this code https://stackoverflow.com/a/12739968/2003393 but it can't solved my problem..
please help me...i'm stuck
thank in advance.
here is my code from fragment activity (MainActivity)
public class Swipe_Menu extends FragmentActivity {
//String KeyWord;
//private static final String KEYWORD = "keyword";
private ViewPager _mViewPager;
private ViewPagerAdapter _adapter;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.swipe_menu_image);
Button Back = (Button)findViewById(R.id.account);
ImageButton Search = (ImageButton)findViewById(R.id.search);
EditText Keyword = (EditText)findViewById(R.id.keyword);
final String KeyWord = Keyword.getText().toString();
/**
* Back button click event
* */
Back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
finish();
}
});
setUpView();
setTab();
}
protected void sendValueToFragments(String value) {
// it has to be the same name as in the fragment
Intent intent = new Intent("my_package.action.UI_UPDATE");
intent.putExtra("UI_KEY", KeyWord );
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
and here is my fragment (Child Activity)
public class Store_Swipe extends Fragment {
public static final String ACTION_INTENT = "my_package.action.UI_UPDATE";
String KeyWord;
private TextView kata_keyword;
protected BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(ACTION_INTENT.equals(intent.getAction())) {
String value = intent.getStringExtra("UI_KEY");
updateUIOnReceiverValue(value);
}
}
};
private void updateUIOnReceiverValue(String value) {
// you probably want this:
KeyWord = value;
}
public static Fragment newInstance(Context context) {
Store_Swipe f = new Store_Swipe();
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter(ACTION_INTENT);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(receiver, filter);
}
#Override
public void onDestroy() {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
super.onDestroy();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/*Bundle bundle = this.getArguments();
KeyWord = bundle.getString("keyword");*/
View view = inflater.inflate(R.layout.store_swipe, container, false);
init(view);
return view;
}
void init(View view) {
kata_keyword = (TextView) view.findViewById(R.id.keyword);
//ImageView image = (ImageView) view.findViewById(R.id.image_error);
kata_keyword.setText(KeyWord);
}
}
You don't have access directly to your fragments that reside in ViewPager so you can't reference them directly.
What I am doing in these cases is send a broadcast message from Activity to Fragments. For this reason register a BroadcatReceiver in the fragment (either in onCreate or onCreateView - your decision)m, set a custom action for that receiver (ex. "my_package.actions.internal.BROADCAST_ACTION"), don't forget to unregister the receiver from complementary method.
When you want to send a message from activity, create an intent with above mentioned action, add the string in intent extra and send the broadcast.
In your receiver's onReceive method (within the fragment), get the String from intent paramter and there you have the string.
Makes sense?
EDIT: To provide some code, below are the changes that I would make for fragment:
public class Store_Swipe extends Fragment {
public static final String ACTION_INTENT = "my_package.action.UI_UPDATE";
protected BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(ACTION_INTENT.equals(intent.getAction())) {
String value = intent.getStringExtra("UI_KEY");
updateUIOnReceiverValue(value);
}
}
};
private void updateUIOnReceiverValue(String value) {
// you probably want this:
kata_keyword.setText(value);
}
String KeyWord;
private TextView kata_keyword;
public static Fragment newInstance(Context context) {
Store_Swipe f = new Store_Swipe();
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter(ACTION_INTENT);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(receiver, filter);
}
#Override
public void onDestroy() {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
super.onDestroy();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle bundle = this.getArguments();
KeyWord = bundle.getString("keyword");
View view = inflater.inflate(R.layout.store_swipe, container, false);
init(view);
return view;
}
void init(View view) {
kata_keyword = (TextView) view.findViewById(R.id.keyword);
ImageView image = (ImageView) view.findViewById(R.id.image_error);
kata_keyword.setText(KeyWord);
}
}
And this code I would have from activity, the parameter is the value from EditText:
protected void sendValueToFragments(String value) {
// it has to be the same name as in the fragment
Intent intent = new Intent("my_package.action.UI_UPDATE");
intent.putExtra("UI_KEY", value);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
You would call this from the click listener that you would set in onCreate:
findViewById(R.id.button_id).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String valueThatYouWantToSend = null; /// just the value
sendValueToFragments(valueThatYouWantToSend);
}
});
// I think this solution will solved your issue
// In Main activity put your code -----------------------------------
public void onPageSelected(int position)
{
System.out.println("nilesh");
PageOneFragment f = new PageOneFragment();
f.getText();
PageTwoFragment ff = new PageTwoFragment();
ff.setText();
}
//in General Class ------------------------------------------------
public class General
{
public static String name="";
}
// first Fragment ---------------------------------------------
public void getText()
{
General.name = edittext.getText().toString();
}
// second Fragment ----------------------------------------------
public void setText()
{
System.out.println("name**" + General.name);
tv.setText(General.name);
}

Categories

Resources