Hi I'm developing an android application and have two activities that are practically the same, but load different data. I currently have two Activities with a lot of duplicate code and I feel I can optimise it by using only one activity.
Activity 1:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.right_hearing_test);
String topHtml = this.getString(R.string.top_content);
String bottomHtml = this.getString(R.string.bottom_content);
View infoButton = findViewById(R.id.info_button);
infoButton.setVisibility(View.VISIBLE);
TextView titleText = (TextView) findViewById(R.id.title_text);
titleText.setText(R.string.Hearing_Test);
mScrollButton = (ScrollView) findViewById(R.id.scroll_view);
topContent = (WebView) findViewById(R.id.top_content);
topContent.setBackgroundColor(0);
bottomContent = (WebView) findViewById(R.id.bottom_content);
bottomContent.setBackgroundColor(0);
activityHelper = new ActivityHelper(this);
topContent.loadUrl("file:///android_asset/html/" + topHtml);
bottomContent.loadUrl("file:///android_asset/html/" + bottomHtml);
getScreenSize();
getMargins();
setResult(RESULT_OK);
}
Activity 2
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.left_hearing_test);
View infoButton = findViewById(R.id.info_button);
infoButton.setVisibility(View.VISIBLE);
mScrollButton = (ScrollView) findViewById(R.id.scroll_view);
topContent = (WebView) findViewById(R.id.top_content);
topContent.setBackgroundColor(0);
bottomContent = (WebView) findViewById(R.id.bottom_content);
bottomContent.setBackgroundColor(0);
String topHtml = this.getString(R.string.switch_file);
String bottomHtml = this.getString(R.string.bottom_content);
activityHelper = new ActivityHelper(this);
topContent.loadUrl("file:///android_asset/html/" + topHtml);
bottomContent.loadUrl("file:///android_asset/html/" + bottomHtml);
getScreenSize();
getMargins();
}
I Load certain data into the web views and the button in activity 1, then the user does a test, which then take the user to activity 2. Here all it does is display different data in the web views and the button.
My question is if I reuse one activity for both pages, how do I load the correct data into each one and is it even possible?
I've used a helper class for a lot of other methods I use on both activities by passing the context in, but I would like to use only one activity for the different content I display in the webviews and the button!
Thanks for any input!
Simply keep a flag to decide which option to chose..
Bellow will give you an idea how to control it.
You can control this flag unisg getStringExtra(), putStringExtra()
For example. you will start your activity from FromActivity class.
FromActivity.java
.......
Intent i = new Intent(FromActivity.this,YourActivity.class);
i.putExtra("Flag","optionone");
startActivity(i);
.......
or
..
Intent i = new Intent(FromActivity.this,YourActivity.class);
i.putExtra("Flag","optiontwo");
startActivity(i);
...
YourActivity.java
#Override
public void onCreate(Bundle savedInstanceState) {
......
..
..
String flag = String.valueOf(getIntent().getStringExtra("Flag"));
if(flag.equalsIgnoreCase("optionone")){
String topHtml = this.getString(R.string.top_content);
String bottomHtml = this.getString(R.string.bottom_content);
TextView titleText = (TextView) findViewById(R.id.title_text);
titleText.setText(R.string.Hearing_Test);
}else if(flag.equalsIgnoreCase("optiontwo")){
String topHtml = this.getString(R.string.top_content);
String bottomHtml = this.getString(R.string.bottom_content);
}else{
}
.....
...
...
if(flag.equalsIgnoreCase("optionone")){
setResult(RESULT_OK);
}
....
}
1) You can put most of the common data in one BaseActivity and then make two activities extending it. And then load data in individual activities as per your requirement.
Related
So I have two activities and in the second one there is a edittext and a button. When you type in some number/s in the edittext and when you press the button it should change the fontsize of all the textviews in the first activity corresponding to the number/s you type in. I did in a certain way but my mentor said it shouldnt be like I did it. Can you please help me with another way of doing this ? Probably more simpler than this. I will post the code.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Switch buttonChangeColors = findViewById(R.id.buttonChangeColors);
Button buttonToGoBackToMainActivity = findViewById(R.id.buttonToGoBackToMainActivity);
Button buttonChangeFontSizeOfCalculator = findViewById(R.id.buttonChangeFontSizeOfCalculator);
editTextInsertSize = findViewById(R.id.editTextInsertSize);
buttonChangeFontSizeOfCalculator.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
float fontSize = Float.parseFloat(editTextInsertSize.getText().toString());
textViewNumberZero = MainActivity.mainActivity.findViewById(R.id.textViewNumberZero);
textViewNumberOne = MainActivity.mainActivity.findViewById(R.id.textViewNumberOne);
textViewNumberTwo = MainActivity.mainActivity.findViewById(R.id.textViewNumberTwo);
textViewNumberThree = MainActivity.mainActivity.findViewById(R.id.textViewNumberThree);
textViewNumberFour = MainActivity.mainActivity.findViewById(R.id.textViewNumberFour);
textViewNumberFive = MainActivity.mainActivity.findViewById(R.id.textViewNumberFive);
textViewNumberSix = MainActivity.mainActivity.findViewById(R.id.textViewNumberSix);
textViewNumberSeven = MainActivity.mainActivity.findViewById(R.id.textViewNumberSeven);
textViewNumberEight = MainActivity.mainActivity.findViewById(R.id.textViewNumberEight);
textViewNumberNine = MainActivity.mainActivity.findViewById(R.id.textViewNumberNine);
textViewOperationEquals = MainActivity.mainActivity.findViewById(R.id.textViewOperationEquals);
textViewOperationAdd = MainActivity.mainActivity.findViewById(R.id.textViewOperationAdd);
textViewOperationSubtract = MainActivity.mainActivity.findViewById(R.id.textViewOperationSubtract);
textViewOperationMultiply = MainActivity.mainActivity.findViewById(R.id.textViewOperationMultiply);
textViewOperationDivide = MainActivity.mainActivity.findViewById(R.id.textViewOperationDivide);
textViewOperationClear = MainActivity.mainActivity.findViewById(R.id.textViewOperationClear);
textViewOperationClearAll = MainActivity.mainActivity.findViewById(R.id.textViewOperationClearAll);
textViewNumberZero.setTextSize(fontSize);
textViewNumberOne.setTextSize(fontSize);
textViewNumberTwo.setTextSize(fontSize);
textViewNumberThree.setTextSize(fontSize);
textViewNumberFour.setTextSize(fontSize);
textViewNumberFive.setTextSize(fontSize);
textViewNumberSix.setTextSize(fontSize);
textViewNumberSeven.setTextSize(fontSize);
textViewNumberEight.setTextSize(fontSize);
textViewNumberNine.setTextSize(fontSize);
textViewOperationAdd.setTextSize(fontSize);
textViewOperationSubtract.setTextSize(fontSize);
textViewOperationMultiply.setTextSize(fontSize);
textViewOperationDivide.setTextSize(fontSize);
textViewOperationEquals.setTextSize(fontSize);
textViewOperationClear.setTextSize(fontSize);
textViewOperationClearAll.setTextSize(fontSize);
}
});
}
A simple idea you can consider:
Create a middleware to listen event from activity2 and notify to activity1.
Activity1 will observe to Middleware.
You can also read Guide to app architecture to clarify how to do it.
To solve this problem, you'd better review data transfer with intent.And using that many findViewById may cause the application to run slower. You should use ViewBinding instead of findViewById.
I have created an pop up window that I can use to show important messages in my app. The code for this are written in PopActivity.
Here is my code:
public class PopActivity extends Activity {
private WorkOutClass the_workout_class = new WorkOutClass();
private TextView repTextField, setsTextField;
private Button den_knappen;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pop);
repTextField = (TextView) findViewById(R.id.repetitionID);
setsTextField = (TextView) findViewById(R.id.setsID);
den_knappen = (Button) findViewById(R.id.buttonID);
repTextField.setText("Reps : " + String.valueOf(the_workout_class.getReps()));
setsTextField.setText("Sets: " +String.valueOf(the_workout_class.getSets()));
DisplayMetrics thePopUpWindow = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(thePopUpWindow);
int width = thePopUpWindow.widthPixels;
int height = thePopUpWindow.heightPixels;
getWindow().setLayout((int)(width*.8), (int)(height*.7));
WindowManager.LayoutParams params = getWindow().getAttributes();
params.gravity = Gravity.CENTER;
params.x = 0;
params.y = 20;
getWindow().setAttributes(params);
den_knappen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
the_workout_class.increaseReps();
repTextField.setText("Reps : " + String.valueOf(the_workout_class.getReps()));
setsTextField.setText("Sets: " +String.valueOf(the_workout_class.getSets()));
}
});
}}
My question is though: If i want to use the same type of pop-up window somewhere else in my app which provide a different message, is there a way I can just copy this to use it? Or do I need to create new file such as PopActivity2, PopActivity3 etc etc.?
Thanks for answer.
Sounds to me that what you really need is a Dialog. You can create your own layout and texts for a dialog, and then use it where ever you need it. These links can help you with that:
https://developer.android.com/guide/topics/ui/dialogs
How do I display an alert dialog on Android?
How to set dialog to show in full screen?
You can pass your data via Intent when you start your Activity like
// in previous activity
Intent intent = new Intent(this, PopActivity.class);
intent.putExtra("first", "your message")
startActivity(intent);
// in PopActivity
String message = getIntent().getStringExtra("first")
and use this as the message your need. You can pass more data if you want. Best would be to define a constant for the name ("first") with a better name and use this on both Activities ;-)
Before I asked this question I really looked at different answers on StackOwerflow for days, but I couldn't find an answer.
This is my what I am doing - I have an app that has UserProfileActivity, which I want to be able to open from 2 different activities - from myContactsListActivity and from messageActivity. Data I want sent in my UserProfileActivity contains userId, userName, profilePhooto, and aboutUser.
In the first case I want to pass this data via intent from myContactsListActivity, and in the second I want to pass only userId from myContactsListActivity and make a call to get data from the server.
This is how I do it right now. When it is open from myContactsListActivity, I use intents to pass the data to UserProfileActivity, and pass only userId from messageActivity, and use if else to determine what intent is called.
In short: Activity A can be opened from activity B and C. I need two different behaviors. If it is opened form B everything is passed via intent, and if it is opened from C only userId is passed and there is a call to server. How would I determine from which activity was opened, and what is the best way to set different behaviors.
Here is my code, IT WORKS, but I am not happy with it, and I am looking for a better solution:
TextView textViewUserName, textViewAbout;
ImageView imageView;
Toolbar toolbar;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_profile);
Intent intent = getIntent();
final String userId = intent.getStringExtra("userId");
String userName = intent.getStringExtra("userName");
String about = intent.getStringExtra("about");
String image = intent.getStringExtra("image");
toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
textViewUserName = (TextView) findViewById(R.id.contactUsername);
textViewAbout = (TextView) findViewById(R.id.aboutMe);
ColorGenerator generator = ColorGenerator.MATERIAL;
final int color = generator.getColor(userId);
TextDrawable.IBuilder builder = TextDrawable.builder()
.beginConfig()
.withBorder(1)
.endConfig()
.rect();
if (userName != null) {
String firstLetter = intent.getStringExtra("userName").substring(0, 1);
TextDrawable textDrawable = TextDrawable.builder().buildRect(firstLetter, color);
imageView = (ImageView) findViewById(R.id.profile_image);
imageView.setImageDrawable(textDrawable);
Picasso.with(this)
.load("http://192.168.0.13/mynewapp/profilephotos/" + image)
.placeholder(textDrawable)
.error(textDrawable)
.centerCrop()
.fit()
.into(imageView);
getSupportActionBar().setTitle(userName);
Intent commentDescriptionIntent = new Intent(this, AboutFragment.class);
commentDescriptionIntent.putExtra("userId", userId);
commentDescriptionIntent.putExtra("userName", userName);
commentDescriptionIntent.putExtra("about", about);
setIntent(commentDescriptionIntent);
} else {
ApiInterface apiService =
ApiClient.getClient().create(ApiInterface.class);
Call<ContactResponse> call = apiService.userExists(userId);
call.enqueue(new Callback<ContactResponse>() {
#Override
public void onResponse(Call<ContactResponse> call, retrofit2.Response<ContactResponse> response) {
Contact contact = response.body().getResults();
String firstLetter = contact.getUserName().substring(0, 1);
TextDrawable textDrawable = TextDrawable.builder().buildRect(firstLetter, color);
imageView = (ImageView) findViewById(R.id.profile_image);
imageView.setImageDrawable(textDrawable);
Picasso.with(getApplicationContext())
.load("http://localhost/mynewapp/profilephotos/" + contact.getThumbnailUrl())
.placeholder(textDrawable)
.error(textDrawable)
.centerCrop()
.fit()
.into(imageView);
CollapsingToolbarLayout collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
String userName = contact.getUserName();
collapsingToolbarLayout.setTitle(userName);
}
#Override
public void onFailure(Call<ContactResponse> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
}
Try using an another extra value with your Intent.
For example:
From ActivityB:
Intent intent = new Intent(ActivityB.this, ActivityA.class);
intent.putExtra("FROM_ACTIVITY", "B");
// Others extra values
startActivity(intent);
From ActivityC:
Intent intent = new Intent(ActivityC.this, ActivityA.class);
intent.putExtra("FROM_ACTIVITY", "C");
// Others extra values
startActivity(intent);
Do this in your ActivityA:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_profile);
String fromActivity = getIntent().getStringExtra("FROM_ACTIVITY");
if(fromActivity.equals("B")) {
// Do something
} else if(fromActivity.equals("C")) {
// Do something
}
}
Hope this will help~
This is how I would go on doing this, We can use fragments to load on activities, depending on the different state of the activity,
So you can have 2 different fragments. Will probably load the same UI/xml view, But behave differently, One just set the values coming from the intent. and Other loading stuff from an external api.
Note:
Try to use a loader to load stuff from an external api. that has its own call backs that you can use to load data after they are being received.
This is more of a high level idea, Let me know if you have any further questions
I have set myself up an array with questions and answers as follows:
static String[][] question= new String[20][5];
{
question[0][0] = "what is my name?";
question[0][1] = "Mark";
question[0][2] = "Steven";
question[0][3] = "Alan";
question[0][4] = "Bob";
question[1][0] = "what is my age?";
question[1][1] = "30";
question[1][2] = "31";
question[1][3] = "32";
question[1][4] = "33";
}
first square brackets indicates the question number and the second number gives the answer number, all correct answers are in 4th answer.my intention is to build a general app of questions that randomize and to pass to the next screen. I have used this code to generate a random number for the question number. so for e.g. 1st attempt Q5 will come up, attempt 2 Q3 could come up, attempt 3 Q1 could come up etc.
This next block of code is used by the android:onClick="goToQuestions"
public void goToQuestions (View v)
{
Intent intent = new Intent (this, Questions.class);
startActivity(intent);
}
using the above code will successfully move from current activity to questions activity. If i use this code below:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_questions);
final TextView textView1 = (TextView) findViewById(R.id.textView1);
final Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
int randomArray = (int) (Math.random() *4);
textView1.setText(question[randomArray][0]);
}
});
}
it will allow me to generate a random number from the array of questions and print it to my text view when it is in the same activity. I have tried this code below to try to pass the information to the questions screen from the home screen:
public void goToQuestions (View v1)
{
final TextView textView1 = (TextView) findViewById(R.id.textView1);
int randomArray = (int) (Math.random() * 4);
textView1.setText(Questions.question[randomArray][0]);
Intent intent = new Intent (this, QuizActivity.class);
startActivity(intent);
}
I have assumed calling android:onClick eliminated the need for an onclick listener. Can anyone provide assistance for how I could finish this correctly. With that last piece of code the app just crashes as I hit the button.
Your data model is not ideal. Create a class that represents a question, and is Parcelable, so you can pass that to your next activity. Something like this
public class Question implements Parcelable {
private final String mQuestion;
private final List<String> mAnswers;
private final int mCorrectAnswer;
public Question(final String question, final List<String> answers, int correctAnswer) {
mQuestion = question;
mAnswers = answers;
mCorrectAnswer = correctAnswer;
}
// implement parcelable interface below
}
Then you would receive this on your next activity, deserialize it and show the data as you see fit.
Consider also using fragments instead of activities.
Found my issue, firstly thank you all for your assistance. Secondly I was able to do this task using the code I was using, I was just putting it into the wrong class files. I was able to move this code:
final TextView textView1 = (TextView) findViewById(R.id.textView1);
int randomArray = (int) (Math.random() * 4);
textView1.setText(Questions.question[randomArray][0]);
into my onCreate method and it worked fine.
I have a Activity which is called SpotDetails, in the onCreate i starts a AsyncTask in another activity. The AsyncTask then downloads and parses an xml file and the result should be outputted into a TextView in the SpotDetails Activity.
How do i accomplish this ?
Snippet from main class (SpotDetails) :
public TextView TextView_WindStrenghFromVindsiden, spoTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.spot_overview);
//Recive intent
Intent intent = getIntent();
//Set strings to information from the intent
//Create a intance of Place with information
place = vindsiden.createSted(intent.getStringExtra("StedsNavn"));
// TextView spoTextView = (TextView)findViewById(R.id.spot_overview_WindDegreesForeCastFromYRinfo);
spoTextView = (TextView)findViewById(R.id.spot_overview_WindDegreesForeCastFromYRinfo);
String URL = place.getNB_url();
DomXMLParser domXMLParser = new DomXMLParser();
//domXMLParser.DownloadXML(URL);
domXMLParser.DownloadXML(URL, this);
//
Snippet from AsyncTask (DomXMLParser.java) :
TextView tv;
#Override
protected void onPreExecute() {
super.onPreExecute();
tv = (TextView) spotDetails.findViewById(R.id.spot_overview_WindDegreesForeCastFromYRinfo);
// Create a progressbar
-----Snippet from onPostExecute
tv.setText(yrMeasurmentList.get(0).getWindDirection_degree());
Exception :
http://pastebin.com/WEqSdc1t
(StackOwerflow woth recognize my Exception as code. )
Don't put your AsyncTask in another activity. If you have AsyncTasks you are using in various places, you can either put them in a utility class or declare them in their own files. If you have an AsyncTask which modifies the UI of only one activity, it should be declared in that activity. If the AsyncTask is used by multiple activities, then you could pass the Activity in the constructor, store it as a private field, and resolve the views in onPostExecute():
class MyAsyncTask extends AsyncTask... {
WeakReference<Activity> mActivity;
public MyAsyncTask( Activity activity ) {
super();
mActivity = new WeakReference<Activity>( activity );
}
...
public void onPostExecute(...) {
Activity act = mActivity.get();
if( act != null ) {
TextView tv = act.findViewById( ...id... );
tv.setText( "Hello World" );
} else {
// the Activity was destroyed
}
}
}
Note: I'm using a WeakReference there which will help alleviate most issues with long running AsyncTasks.