I want to use common function in multiple activity. How can I achieve this?
In my application I am displaying a Dialog box which have some data coming from some api. And this Dialog box, used in multiple activities. Right now I have implemented same Dialog box in all activities. Now I want common Dialog box for all activities. I am using this Dialog box in activity as well in adapter.
How could I do this? Using extends or using fragment.
I am already extending some class so I can not extend again( As I read, we can not extends more than one class.).
Also I want to pass some value to this function and based on return value I want to call another function.
private boolean allGroupsEdit(final String type) {
String allGroups = "allGroups";
final String url = Constants.CONSTANT_SERVER_URL + Constants.CONSTANT_GET_GROUPS_URL;
final ProgressDialog dialog = new ProgressDialog(context);
dialog.setMessage(context.getResources().getString(R.string.please_wait));
dialog.show();
StringRequest allGroupsRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String s) {
final SharedPreferences sharedPreferencesRemember = PreferenceManager.getDefaultSharedPreferences(context);
sessionGroupId = sharedPreferencesRemember.getString(Constants.CONSTANT_session_group_id, "");
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray jsonArray = jsonObject.optJSONArray(Constants.CONSTANT_data);
int a = jsonArray.length();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject schObj = jsonArray.optJSONObject(i);
schData = schObj.optJSONArray(Constants.CONSTANT_data);
}
dialog.dismiss();
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.setContentView(R.layout.dialog_checkbox_options);
Window window = dialog.getWindow();
window.setLayout(DrawerLayout.LayoutParams.MATCH_PARENT, DrawerLayout.LayoutParams.WRAP_CONTENT);
if(..someting){
editPublicComments(type);
}else{
editPublicPosts(type);
}
}catch(){}
}
}
Note: This a very long function so I am pasting some code for basic understand. If u need anything more detail let me know. Thanks in advance and editing and suggestions are welcome.
Edit_1: I want this whole function to be common.
Edit_2: How to return value to activity from utils ?
Edit_3: Now I created a static function in a class and I am able to call it from my activity. Now I want call another function based on common function result. (I am using SharedPreferences to store value of common function).
But in my activity where I called a common function, I doesn't execute common function first. It call another function then It call common function and after completing common method, it doesn't call another method again.
All I want to call another function based on result of common function which is true or false
boolean abab = CommonGroupBox.allGroupsEdit(context,"share", selectedPostId, localGrpArray);
if (abab){
boolean pubFlag = pref.getBoolean("isPublicFlag", false);
String qType = pref.getString("questionType","0");
if (pubFlag) {
editPublicComments(qType);
}else{
ediComments(qType);
}
else{
boolean pubFlag = pref.getBoolean("isPublicFlag", false);
String qType = pref.getString("questionType","0");
if (pubFlag) {
PublicComments(qType);
}else{
Comments(qType);
}
}
Here it doesn't call CommonGroupBox.allGroupsEdit firsts. It is called after if and else loop.
Just create a normal java class
public class Utility {
//your common method
public static void showDialog(Context context,int type){
//TODO task
}
}
Now you can use the showDialog method any where in your application
Utility.showDialog(ctx,type);
You can create an abstract class which extends AppCompatActivity, implement your method there and make all your other activities extend this class:
public abstract class BaseActivity extends AppCompatActivity {
protected boolean allGroupsEdit(final String type) {
// ...
}
// Other methods
}
Then implement your activity as :
public class MainActivity extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
allGroupsEdit("Some type");
}
...
To create a Utility Class:
1) Create a Java file with name AppUtil which extends Activity.
2) Select a common method that you are going to use in your Application.
3) Write the function in AppUtil java file
4) Make all the function as static in your Java file so it can be easy to call inside your activity (example: AppUtil.yourMethod() )
5) Pass the context of your Activity.
Here is a simple example to check internet connection:
public class AppUtilities extends Activity {
public static boolean isInternetConnected(Context context) {
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting() &&
netInfo.isAvailable();
}
}
And you can easily call this method from anywhere in your Application
example ::
AppUtilities.isInternetConnected(YourActivity.this);
Related
I have a class 'Common' and a fragment 'FragmentTest'. The 'Common.java' is a general class that have some common functions for other activities..Those functions are accessed by context of each activities.. And here I am passing the fragment's context to a function in that class. I am doing like this
In Fragment :-
Common commonObj = new Common();
commonObj.myfunction(this.getActivity(),"Do you want to Update ?");
And in Class after some operation i'm trying to return back to fragment class.Like this
:-
public void myfunction(Context context , String str){
//....//
if(context.getClass().isInstance(FragmentTest.class)){
**FragmentTest mContext = (FragmentTest)context;**
mContext.FunctionInFragment();
}
}
But i have error in this..Because i cannot cast the context to fragment reference.
Somebody please help..
Firstly you can't cast a Context to a Fragment as Fragment doesn't extend Context. Activity does extend Context which is why when you do this from an Activity what you are trying works.
I'd suggest ideally that the methods in your Common class should be totally unaware of the existence of your Fragment. This way they are not 'coupled' together. To achieve this you can use a callback interface.
Create an interface as follows:
public interface Callback<T> {
onNext(T result);
}
Then you can change your method in Common to the following:
public void myfunction(Callback<Void> callback , String str){
//....//
callback.onNext(null);
}
Then when you call the method in Common from the Fragment you would do it like this:
Common commonObj = new Common();
commonObj.myfunction(
new Callback<Void>() {
#Override
public void onNext(Void result) {
functionInFragment();
}
},
"Do you want to Update ?"
);
If you needed to send data back to the function then you can change the return type of the callback. For instance if you wanted to pass back a string you would use Callback<String> and then the method in the original call would look like this:
new Callback<String>() {
#Override
public void onNext(String result) {
}
}
And in your Common class you would call it like this:
public void myfunction(Callback<String> callback , String str){
//....//
String result = "Hello from common";
callback.onNext(result);
}
You can do something like this:
public void myfunction(BaseFragment fragment, String str){
//....//
if(fragment.getClass().isInstance(FragmentTest.class)){
FragmentTest fr = (FragmentTest) fragment;
fr.FunctionInFragment();
}
}
i.e. using some base fragment(BaseFragment) and inherit from it.
I have my login. The user types his username and password in EditText and press onClick login button.
public void onClick(View v) {
String username = ((EditText) findViewById(R.id.typeUsername)).getText().toString();
String password = ((EditText) findViewById(R.id.typePassword)).getText().toString();
Controller handler = new Controller(getBaseContext());
if (!username.equals("") || !password.equals("")) {
//new LoginTask().execute(((EditText)findViewById(R.id.typeUsername)).getText().toString(),
// ((EditText)findViewById(R.id.typePassword)).getText().toString());
LoginTask load = new LoginTask(context);
load.execute();
} else {
Toast.makeText(getApplicationContext(), "Please fill in all fields", Toast.LENGTH_SHORT).show();
return;
}
}
Now when the login button is clicked. It executes LoginTask in the same class.
In the LoginTask when the login button is clicked a dialog should show, and in the background the user input is checked with the SQL. executeLog is a method in my DatabaseHelper it is a rawQuery to the SQL checking if username and password matches. saveLogin() is another method in my sharedpref class that saves the username and password in sharedPreference.
My issue is how can I execute? LoginTask properly in the Login class? Do i need to pass anything? What should I use in LoginTask instead of getApplicationContext
The correct way to use a Context reference in your AsyncTask is like this:
private static class ExampleTask extends AsyncTask<Void, Void, String> {
private final WeakReference<Context> contextReference;
private ExampleTask(Context context) {
this.contextReference = new WeakReference<Context>(context);
}
#Override
protected String doInBackground(Void... params) {
final Context context = this.contextReference.get();
if(context != null) {
// Inside this if you can safely use the context variable
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
final Context context = this.contextReference.get();
if(context != null) {
// Inside this if you can safely use the context variable
}
}
}
What the WeakReference does is it allows the garbage collector to destroy the Activity or Context even though your AsyncTask still has a reference to it and as such prevents the creation of memory leaks. If you want to use the Context inside your AsyncTask you need to call get() on the WeakReference like in the example above and perform a null check. If the Context you get from get() is not null you can safely use it.
Your LoginTask is declared as static class, so you don't have acces to instance of Login. Althrough you are trying to access Intent log member.
LoginTask is declared static and it has not access to the outer environment. So neither Intent log or getApplicationContext() are visible from your AsyncTask. Also notice that your AsyncTask try to access not-intialized class member. E.g Controller handler; in the AsyncTask's scope, is never intialized. When doInBackground will be executed it will cause a NPE
What I am trying to achive is a single AsynTask that can check if a user has access to a certain fragment in my application that can be called from various fragments.
I am not sure that this is even possible so thought I would ask here, this is my latest attempt
public class HasAccess extends AsyncTask<Void,Void,Void> {
Context ctx;
String AppName;
IInterface i;
int AccessGranted;
public HasAccess(Context _ctx, String _AppName, IInterface _i)
{
this.ctx = _ctx;
this.AppName = _AppName;
this.i = _i;
}
#Override
protected Void doInBackground(Void... params) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
int UserID = Integer.parseInt(prefs.getString("prefs_userid", null));
PermsTableOps PTO = new PermsTableOps(ctx);
int AccessGranted = PTO.hasAccess(AppName,UserID);
return null;
}
#Override
protected void onPostExecute(Integer integer) {
i.Access(AccessGranted);
}
}
So basically from various fragments I would like to be able to call this task, each of these fragments has its own interface, what I want to avoid is creating an AsyncTask for each interface.
I hope this is clear enough!
Edit I think the code above is confusing the issue so I have provided a theoretical example:
Fragment 1 inherits interface 1
Fragment 2 inherits interface 2
AsyncTask 1
Both fragment 1 and fragment 2 call AsyncTask1 - I want a response sent to my fragment from the asynctask whether it is called from either fragment 1 or fragment 2, by sending in the relevant interface.
I hope this is clearer.
Related to my previous question about ANR problem (Android - Strings.xml versus text files. Which is faster?).
I tried using AsyncTask as advised by the respondents but i'm at a loss now.
I need to pass a string from my menu activity to an Asynctask but it's really confusing me. I've been searching and studying for 5 hours already but still cannot do it.
Here's a snippet of my code:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
/** Create an option menu from res/menu/items.xml */
getMenuInflater().inflate(R.menu.items, menu);
/** Get the action view of the menu item whose id is search */
View v = (View) menu.findItem(R.id.search).getActionView();
/** Get the edit text from the action view */
final EditText txtSearch = ( EditText ) v.findViewById(R.id.txt_search);
/** Setting an action listener */
txtSearch.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
final EditText txtSearch = ( EditText ) v.findViewById(R.id.txt_search);
String enhancedStem = txtSearch.getText().toString();
TextView databaseOutput = (TextView)findViewById(R.id.textView8);
new AsyncTaskRunner().execute();
// should I put "enhancedStem" inside execute?
}
});
return super.onCreateOptionsMenu(menu);
}
Here's the Async part: UPDATED
public class AsyncTaskRunner extends AsyncTask<String, String, String> {
String curEnhancedStem;
private ProgressDialog pdia;
public AsyncTaskRunner (String enhancedStem)
{
this.curEnhancedStem = enhancedStem;
}
#Override
protected void onPreExecute() {
// Things to be done before execution of long running operation. For
// example showing ProgessDialog
super.onPreExecute();
pdia = ProgressDialog.show(secondactivity.this, "" , "Searching for words");
}
#Override
protected String doInBackground(String... params) {
if(curEnhancedStem.startsWith("a"))
{
String[] wordA = getResources().getStringArray(R.array.DictionaryA);
String delimiter = " - ";
String[] del;
TextView databaseOutput1 = (TextView)findViewById(R.id.textView8);
for (int wordActr = 0; wordActr <= wordA.length - 1; wordActr++)
{
String wordString = wordA[wordActr].toString();
del = wordString.split(delimiter);
if (curEnhancedStem.equals(del[0]))
{
databaseOutput1.setText(wordA[wordActr]);
pdia.dismiss();
break;
}
else
databaseOutput1.setText("Word not found!");
}
}
return null;
}
#Override
protected void onProgressUpdate(String... text) {
// Things to be done while execution of long running operation is in
// progress. For example updating ProgessDialog
}
#Override
protected void onPostExecute(String result) {
// execution of result of Long time consuming operation
}
}
Retrieval now works. I saw it display the word being looked for but it terminated suddenly.
Maybe because, like what you mentioned, UI stuff should be done on the post execute.
If that's the case, what should I return on the doInBackground() part then pass on the onPostExecute()?
(Thanks a lot guys! I'm close to making this work properly now!)
That's the problem, they are local to the method that you declared them in then you are declaring an AsyncTask class which doesn't have access to them. If the AsyncTask is an inner class of your menu activity then you can declare them as member variables.
public class MenuActivity extends Activity
{
String enhancedStem;
....
If it is a separate class then you can create a constructor in your Async class and pass the variable to the constructor.
public class AsyncTaskRunner extends AsyncTask<String, String, String> {
String curEnhancedStem;
private ProgressDialog pdia;
public void AsyncTaskRunner (String variableName)
{
this.curEnhancedStem = variableName;
}
And call it like
AsyncTaskRunner newTask = new AsyncTaskRunner(enhancedStem);
newTask.execute();
Also, you can't do UI stuff in doInBackground so this will need to be changed in the Activity class or one of your other methods in the Async class such as onPostExecute() if it is an inner class. Otherwise, you can pass a value back to your menu activity to update your TextView
Edit
You are still trying to change the UI in doInBackground() with this
TextView databaseOutput1 = (TextView)findViewById(R.id.textView8);
then again when you call setText(). This needs to be put in your onPostExecute() but then you will need to pass a reference of your TextView to the AsyncTask. You could just pass back the String that you want to set the text as from your onPostExecute() and set it in your Activity. Hope this helps
Create a constructor for your AsyncTaskRunner class.
Pass both a Context (your Activity Context) and the databaseOutput TextView as arguments to your AsyncTaskRunner class constructor.
Save references to those two objects in AsyncTaskRunner.
Pass enhancedStem to the execute() method.
Use the Context you passed to the constructor as the first argument to ProgessDialog.show()
You cannot access databaseOutput from the doInBackground() method. You must only access it in onPostExecute(), which runs on the UI thread. So, use the reference to databseOutput which you passed to the constructor to update the TextView in the onPostExecute() method accordingly.
As a note, anything you return from the doInBackground() method will be available to you as the parameters of the onPostExecute() method.
Please refer to http://developer.android.com/reference/android/os/AsyncTask.html
I would recommend you pass the required data rather than accessing it using the enclosing class - this makes your ASyncTaskRunner much more flexible, and is generally better practice.
I have a problem with a simple class that contains information that I will like to call from another class. For example here is the class Util which contains the info:
public class Util{
public ArrayList<RecetaBean> getRellenas() {
ArrayList<RecetaBean> MiLista = new ArrayList<RecetaBean>();
RecetaBean receta1 = new RecetaBean();
String ingrediente1[] = { getString(R.string.app_name),getString(R.string.app_name),
};
receta1.setIngredientesLista(ingrediente1);
MiLista.add(receta1);
MiLista.add(receta1);
MiLista.add(receta1);
return MiLista;
}
}
Then in another class I get the Items calling like this:
Util u = new Util();
ArrayList<RecetaBean> Recetas = u.getRellenas();
So, I have a execution problem in the class Util with the GETSTRING, because I would like to get a different string (because of different languages). The way to quit the error is to extend the class Util from Activity, but Util is not an Activity! And if I extend from Activity, the app crash.
all you need to do is Define a Context in the Method .
and call it like this;
Util u = new Util();
ArrayList<RecetaBean> Recetas = u.getRellenas(this);
and you the context in you Methods like this:
public ArrayList<RecetaBean> getRellenas(Context con) {
ArrayList<RecetaBean> MiLista = new ArrayList<RecetaBean>();
RecetaBean receta1 = new RecetaBean();
String ingrediente1[] = { con.getString(R.string.app_name), con.getString(R.string.app_name),
};
receta1.setIngredientesLista(ingrediente1);
MiLista.add(receta1);
MiLista.add(receta1);
MiLista.add(receta1);
return MiLista;
}
have you thought about using a string array? It would be so much simpler than what you are trying to do.
I do not think that your concerns about language change are justified, in terms of the overall user experience.