크기를 확인하거나 범위를 벗어나지 않고 문자열의 처음 n자를 얻으려면 어떻게합니까?
먼저 n
크기 검사를 수행하지 않고 (인라인이 허용 가능) 또는 위험을 감수하지 않고 Java에서 문자열 의 첫 문자 를 어떻게 확인 IndexOutOfBoundsException
합니까?
깔끔한 해결책은 다음과 같습니다.
String upToNCharacters = s.substring(0, Math.min(s.length(), n));
의견 :이 솔루션은 "신선한"반면, / 를 명백한 방식으로 사용하는 솔루션보다 실제로 읽기 가 어렵다고 생각합니다 . 독자가이 속임수를 보지 못했다 면 코드를 이해 하기 가 더 어려워 야 합니다. IMO, 코드의 의미는 / 버전 에서 더 분명합니다 . 더 깨끗하고 읽기 쉬운 솔루션은 @paxdiablo의 답변을 참조하십시오.if
else
if
else
바퀴를 재발 명하지 마십시오 ... :
org.apache.commons.lang.StringUtils.substring(String s, int start, int len)
자바 독 은 말한다 :
StringUtils.substring(null, *, *) = null StringUtils.substring("", * , *) = ""; StringUtils.substring("abc", 0, 2) = "ab" StringUtils.substring("abc", 2, 0) = "" StringUtils.substring("abc", 2, 4) = "c" StringUtils.substring("abc", 4, 6) = "" StringUtils.substring("abc", 2, 2) = "" StringUtils.substring("abc", -2, -1) = "b" StringUtils.substring("abc", -4, 2) = "ab"
그러므로:
StringUtils.substring("abc", 0, 4) = "abc"
Apache Commons Lang 에는이를위한 StringUtils.left
방법이 있습니다.
String upToNCharacters = StringUtils.left(s, n);
SO에는 때로는 완벽하게 이해가되지 않는 질문이 있습니다. 이것은 위험에 가깝습니다 :-)
아마도 배제한 두 가지 방법 중 하나를 사용하여 혐오감을 설명 할 수있을 것입니다.
if
명령문이나 예외 잡기 코드로 코드를 작성 하지 않으려는 이유 중 하나는 다음과 같은 도우미 함수를 사용하는 것입니다.
static String substring_safe (String s, int start, int len) { ... }
미리 길이를 확인하고 그에 따라 행동합니다 (작은 줄이나 공백이있는 패드를 반환합니다).
그런 다음 코드에서 전혀 걱정할 필요가 없습니다.
String s2 = substring_safe (s, 10, 7);
대신에:
String s2 = s.substring (10,7);
이것은 많은 문자열 작성 작업을 수행 할 때 코드의 흐름을 깨뜨리지 않고 (다른 답변에 대한 귀하의 의견을 바탕으로) 걱정되는 것처럼 작동합니다.
String upToNCharacters = String.format("%."+ n +"s", str);
n
변수가 if 인 경우 끔찍 하지만 (따라서 형식 문자열을 구성해야 함) 상수가 있으면 매우 분명합니다.
String upToNCharacters = String.format("%.10s", str);
다음과 같이 부분 문자열 방법을 사용하십시오.
int n = 8;
String s = "Hello, World!";
System.out.println(s.substring(0,n);
n이 문자열의 길이보다 크면 한 주석 작성자가 지적한 것처럼 예외가 발생합니다. 하나 개의 간단한 솔루션은 상태에서이 모든 것을 래핑하는 것입니다 if(s.length()<n)
귀하의 else
절, 당신은 단지 / 인쇄 전체 문자열을 반환하거나 다른 방법을 처리할지 여부를 선택할 수 있습니다.
ApacheCommons StringUtils.abbreviate(String str, int maxWidth)
는 "..."를 덧붙이고 접미사를 변경할 수있는 옵션이 없습니다. WordUtils.abbreviate(String str, int lower, int upper, String appendToEnd)
다음 빈 공간을 찾습니다.
나는 이것을 여기에 남겨 둘 것입니다 :
public static String abbreviate(String s, int maxLength, String appendToEnd) {
String result = s;
appendToEnd = appendToEnd == null ? "" : appendToEnd;
if (maxLength >= appendToEnd.length()) {
if (s.length()>maxLength) {
result = s.substring(0, Math.min(s.length(), maxLength - appendToEnd.length())) + appendToEnd;
}
} else {
throw new StringIndexOutOfBoundsException("maxLength can not be smaller than appendToEnd parameter length.");
}
return result;
}
If you are lucky enough to develop with Kotlin,
you can use take
to achieve your goal.
val someString = "hello"
someString.take(10) // result is "hello"
someString.take(4) // result is "hell" )))
개조 2-동적 URL
Retrofit 2를 사용하면 다음과 같은 서비스 방법 주석에 전체 URL개조 2-동적 URL을 설정할 수 있습니다.
public interface APIService {
@GET("http://api.mysite.com/user/list")
Call<Users> getUsers();
}
그러나 내 응용 프로그램에서 웹 서비스의 URL을 컴파일 타임에 알 수 없으며 응용 프로그램이 다운로드 된 파일에서 URL을 검색하므로 전체 동적 URL과 함께 Retrofit 2를 어떻게 사용할 수 있는지 궁금합니다.
나는 다음과 같은 전체 경로를 설정하려고했습니다.
public interface APIService {
@GET("{fullUrl}")
Call<Users> getUsers(@Path("fullUrl") fullUrl);
}
new Retrofit.Builder()
.baseUrl("http://api.mysite.com/")
.build()
.create(APIService.class)
.getUsers("http://api.mysite.com/user/list"); // this url should be dynamic
.execute();
그러나 여기서 Retrofit은 경로가 실제로 전체 URL이며 다운로드하려고한다는 것을 알지 못합니다. http://api.mysite.com/http%3A%2F%2Fapi.mysite.com%2Fuser%2Flist
그런 동적 URL과 함께 Retrofit을 사용하는 방법에 대한 힌트가 있습니까?
감사합니다
나는 당신이 그것을 잘못된 방식으로 사용하고 있다고 생각합니다. 다음은 changelog 에서 발췌 한 것입니다 .
@Url 매개 변수 주석을 사용하면 엔드 포인트에 대한 완전한 URL을 전달할 수 있습니다.
따라서 인터페이스는 다음과 같아야합니다.
public interface APIService {
@GET
Call<Users> getUsers(@Url String url);
}
URL의 일부만 바꾸고 싶었고이 솔루션을 사용하면 전체 URL을 전달할 필요가 없으며 동적 부분 만 전달하면됩니다.
public interface APIService {
@GET("users/{user_id}/playlists")
Call<List<Playlist> getUserPlaylists(@Path(value = "user_id", encoded = true) String userId);
}
주석 에서 인코딩 된 플래그를 사용할 수 있습니다 @Path
.
public interface APIService {
@GET("{fullUrl}")
Call<Users> getUsers(@Path(value = "fullUrl", encoded = true) String fullUrl);
}
- 로 교체하지 못하게
/
됩니다%2F
. - 그것은 당신이 저장에서이되지 않습니다
?
으로 대체%3F
당신은 여전히 동적 쿼리 문자열에 통과 할 수 있도록, 그러나.
Retrofit 2.0.0-beta2부터이 URL에서 JSON에 응답하는 서비스가있는 경우 : http : // myhost / mypath
다음은 작동하지 않습니다.
public interface ClientService {
@GET("")
Call<List<Client>> getClientList();
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://myhost/mypath")
.addConverterFactory(GsonConverterFactory.create())
.build();
ClientService service = retrofit.create(ClientService.class);
Response<List<Client>> response = service.getClientList().execute();
그러나 이것은 괜찮습니다.
public interface ClientService {
@GET
Call<List<Client>> getClientList(@Url String anEmptyString);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://myhost/mypath")
.addConverterFactory(GsonConverterFactory.create())
.build();
ClientService service = retrofit.create(ClientService.class);
Response<List<Client>> response = service.getClientList("").execute();
이것을 사용할 수 있습니다 :
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
자세한 내용은 설명서 https://square.github.io/retrofit/를 참조 하십시오.
1 단계
Please define a method in Api interface like:-
@FormUrlEncoded
@POST()
Call<RootLoginModel> getForgotPassword(
@Url String apiname,
@Field(ParameterConstants.email_id) String username
);
2 단계 모범 사례를 위해 개량 인스턴스의 클래스를 정의하십시오.
public class ApiRequest {
static Retrofit retrofit = null;
public static Retrofit getClient() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.addInterceptor(logging)
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.build();
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(URLConstants.base_url)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
} 3 단계 는 활동을 정의합니다.
final APIService request =ApiRequest.getClient().create(APIService.class);
Call<RootLoginModel> call = request.getForgotPassword("dynamic api
name",strEmailid);
kotlin으로 작성된 RetrofitHelper 라이브러리를 사용하면 몇 줄의 코드를 사용하여 API 호출을 할 수 있으며 모든 호출에서 다른 URL, 헤더 및 매개 변수를 사용할 수 있습니다 .
다음과 같이 애플리케이션 클래스에 여러 개의 URL을 추가하십시오.
class Application : Application() {
override fun onCreate() {
super.onCreate()
retrofitClient = RetrofitClient.instance
//api url
.setBaseUrl("https://reqres.in/")
//you can set multiple urls
// .setUrl("example","http://ngrok.io/api/")
//set timeouts
.setConnectionTimeout(4)
.setReadingTimeout(15)
//enable cache
.enableCaching(this)
//add Headers
.addHeader("Content-Type", "application/json")
.addHeader("client", "android")
.addHeader("language", Locale.getDefault().language)
.addHeader("os", android.os.Build.VERSION.RELEASE)
}
companion object {
lateinit var retrofitClient: RetrofitClient
}
}
그런 다음 전화에 필요한 URL을 사용하십시오.
retrofitClient.Get<GetResponseModel>()
//set base url
.setBaseUrlKey("example")
//set path
.setPath("api/users/2")
//set url params Key-Value or HashMap
.setUrlParams("KEY","Value")
.setResponseHandler(GetResponseModel::class.java,
object : ResponseHandler<GetResponseModel>() {
override fun onSuccess(response: Response<GetResponseModel>) {
super.onSuccess(response)
//handle response
}
}).run(this)
자세한 내용은 설명서를 참조하십시오
step -*1
movie_list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/row_padding_vertical"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/row_padding_vertical">
<ImageView
android:id="@+id/ivImage"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginRight="10dp"
android:src="@mipmap/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="Hello"
android:textColor="@color/title"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="@+id/genre"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:text="realName" />
</LinearLayout>
<TextView
android:id="@+id/year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Team"
android:textColor="@color/year" />
</LinearLayout>
Api.java
import org.json.JSONObject;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
public interface Api {
String BASE_URL = "https://simplifiedcoding.net/demos/";
@GET("marvel")
Call<List<Hero>> getHeroes();
@FormUrlEncoded
@POST("/login")
public void login(@Field("username") String username, @Field("password") String password, Callback<List<Hero>> callback);
}
MoviesAdapter.java import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import java.util.List;
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MyViewHolder> {
private List<Hero> moviesList;
Context context;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title, year, genre;
public ImageView ivImage;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
genre = (TextView) view.findViewById(R.id.genre);
year = (TextView) view.findViewById(R.id.year);
ivImage = view.findViewById(R.id.ivImage);
ivImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "-" + moviesList.get(getAdapterPosition()).getName(), Toast.LENGTH_SHORT).show();
}
});
}
}
public MoviesAdapter(List<Hero> moviesList,Context context) {
this.moviesList = moviesList;
this.context = context;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.movie_list_row, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Hero movie = moviesList.get(position);
holder.title.setText(movie.getName());
holder.genre.setText(movie.getRealname());
holder.year.setText(movie.getTeam());
Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(holder.ivImage);
}
@Override
public int getItemCount() {
return moviesList.size();
}
} main activity import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
private List<Hero> movieList = new ArrayList<>();
private RecyclerView recyclerView;
private MoviesAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView=findViewById(R.id.recycler_view);
mAdapter = new MoviesAdapter(movieList,MainActivity.this);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
//calling the method to display the heroes
getHeroes();
}
private void getHeroes() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) //Here we are using the GsonConverterFactory to directly convert json data to object
.build();
ApiInterface api = retrofit.create(ApiInterface.class);
Call<List<Hero>> call = api.getHeroes();
call.enqueue(new Callback<List<Hero>>() {
@Override
public void onResponse(Call<List<Hero>> call, Response<List<Hero>> response) {
List<Hero> heroList = response.body();
//Creating an String array for the ListView
String[] heroes = new String[heroList.size()];
//looping through all the heroes and inserting the names inside the string array
for (int i = 0; i < heroList.size(); i++) {
//heroes[i] = heroList.get(i).getName();
movieList.add(new Hero( heroList.get(i).getName(), heroList.get(i).getRealname(), heroList.get(i).getTeam()));
}
mAdapter.notifyDataSetChanged();
}
@Override
public void onFailure(Call<List<Hero>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
Hero.java
package com.example.owner.apipractice;
public class Hero {
private String name;
private String realname;
private String team;
public Hero(String name, String realname, String team) {
this.name = name;
this.realname = realname;
this.team = team;
}
private String firstappearance;
private String createdby;
private String publisher;
private String imageurl;
private String bio;
public Hero(String name, String realname, String team, String firstappearance, String createdby, String publisher, String imageurl, String bio) {
this.name = name;
this.realname = realname;
this.team = team;
this.firstappearance = firstappearance;
this.createdby = createdby;
this.publisher = publisher;
this.imageurl = imageurl;
this.bio = bio;
}
public String getName() {
return name;
}
public String getRealname() {
return realname;
}
public String getTeam() {
return team;
}
public String getFirstappearance() {
return firstappearance;
}
public String getCreatedby() {
return createdby;
}
public String getPublisher() {
return publisher;
}
public String getImageurl() {
return imageurl;
}
public String getBio() {
return bio;
}
}
이미 코드 설정이되어 있고 다른 인터페이스를 변경하지 않으려면이 링크에 설명 된 솔루션을 사용하십시오 . 요점은 changeApiBaseUrl
URL을 업데이트하고 추가 빌더를 다시 작성하는 방법 입니다.
public class ServiceGenerator {
public static String apiBaseUrl = "http://futurestud.io/api";
private static Retrofit retrofit;
private static Retrofit.Builder builder =
new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiBaseUrl);
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
// No need to instantiate this class.
private ServiceGenerator() {
}
public static void changeApiBaseUrl(String newApiBaseUrl) {
apiBaseUrl = newApiBaseUrl;
builder = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiBaseUrl);
}
public static <S> S createService(Class<S> serviceClass, AccessToken token) {
String authToken = token.getTokenType().concat(token.getAccessToken());
return createService(serviceClass, authToken);
}
// more methods
// ...
}
다음과 같이 사용할 수 있습니다.
public class DynamicBaseUrlActivity extends AppCompatActivity {
public static final String TAG = "CallInstances";
private Callback<ResponseBody> downloadCallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_upload);
downloadCallback = new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d(TAG, "server contacted at: " + call.request().url());
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d(TAG, "call failed against the url: " + call.request().url());
}
};
// first request
FileDownloadService downloadService = ServiceGenerator.create(FileDownloadService.class);
Call<ResponseBody> originalCall = downloadService.downloadFileWithFixedUrl();
originalCall.enqueue(downloadCallback);
// change base url
ServiceGenerator.changeApiBaseUrl("http://development.futurestud.io/api");
// new request against new base url
FileDownloadService newDownloadService = ServiceGenerator.create(FileDownloadService.class);
Call<ResponseBody> newCall = newDownloadService.downloadFileWithFixedUrl();
newCall.enqueue(downloadCallback);
}
}
Retrofit (MVVM)의 Get 및 Post 메소드가있는 동적 URL
개조 서비스 인터페이스 :
public interface NetworkAPIServices {
@POST()
Observable<JsonElement> executXYZServiceAPI(@Url String url,@Body AuthTokenRequestModel param);
@GET
Observable<JsonElement> executeInserInfo(@Url String url);
MVVM 서비스 클래스 :
public Observable<JsonElement> executXYZServiceAPI(ModelObject object) {
return networkAPIServices.authenticateAPI("url",
object);
}
public Observable<JsonElement> executeInserInfo(String ID) {
return networkAPIServices.getBank(DynamicAPIPath.mergeUrlPath("url"+ID)));
}
Retrofit Client 클래스
@Provides
@Singleton
@Inject
@Named("provideRetrofit2")
Retrofit provideRetrofit(@Named("provideRetrofit2") Gson gson, @Named("provideRetrofit2") OkHttpClient okHttpClient) {
builder = new Retrofit.Builder();
if (BaseApplication.getInstance().getApplicationMode() == ApplicationMode.DEVELOPMENT) {
builder.baseUrl(NetworkURLs.BASE_URL_UAT);
} else {
builder.baseUrl(NetworkURLs.BASE_URL_PRODUCTION);
}
builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
builder.client(okHttpClient);
builder.addConverterFactory(GsonConverterFactory.create(gson));
return builder.build();
}
예를 들어 이것은 URL입니다 : https://gethelp.wildapricot.com/en/articles/549-changing-your
baseURL : https://gethelp.wildapricot.com
@Url 남음 : / en / articles / 549-changing-your (레트로 서비스 클래스에 합격)
참고 URL : https://stackoverflow.com/questions/32559333/retrofit-2-dynamic-url
'IT박스' 카테고리의 다른 글
C # : 단일 명령문에서 동일한 값을 여러 변수에 지정 (0) | 2020.06.13 |
---|---|
C # 대소 문자를 구분하지 않는 equals 연산자가 있습니까? (0) | 2020.06.13 |
Sublime Text에서 여러 커서로 다른 모든 줄을 선택하려면 어떻게해야합니까? (0) | 2020.06.12 |
빌드에서 누락 된 .pch 파일을 고치는 방법? (0) | 2020.06.12 |
배열에서 선택한 모든 확인란을 가져 오기 (0) | 2020.06.12 |